1 2 /* 3 Creates a matrix class for using the Neumann-Neumann type preconditioners. 4 This stores the matrices in globally unassembled form. Each processor 5 assembles only its local Neumann problem and the parallel matrix vector 6 product is handled "implicitly". 7 8 We provide: 9 MatMult() 10 11 Currently this allows for only one subdomain per processor. 12 13 */ 14 15 #include <../src/mat/impls/is/matis.h> /*I "petscmat.h" I*/ 16 17 #undef __FUNCT__ 18 #define __FUNCT__ "MatIsHermitian_IS" 19 PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool *flg) 20 { 21 PetscErrorCode ierr; 22 Mat_IS *matis = (Mat_IS*)A->data; 23 PetscBool local_sym; 24 25 PetscFunctionBegin; 26 ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr); 27 ierr = MPI_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 28 PetscFunctionReturn(0); 29 } 30 31 #undef __FUNCT__ 32 #define __FUNCT__ "MatIsSymmetric_IS" 33 PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg) 34 { 35 PetscErrorCode ierr; 36 Mat_IS *matis = (Mat_IS*)A->data; 37 PetscBool local_sym; 38 39 PetscFunctionBegin; 40 ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr); 41 ierr = MPI_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 42 PetscFunctionReturn(0); 43 } 44 45 #undef __FUNCT__ 46 #define __FUNCT__ "MatDestroy_IS" 47 PetscErrorCode MatDestroy_IS(Mat A) 48 { 49 PetscErrorCode ierr; 50 Mat_IS *b = (Mat_IS*)A->data; 51 52 PetscFunctionBegin; 53 ierr = MatDestroy(&b->A);CHKERRQ(ierr); 54 ierr = VecScatterDestroy(&b->ctx);CHKERRQ(ierr); 55 ierr = VecDestroy(&b->x);CHKERRQ(ierr); 56 ierr = VecDestroy(&b->y);CHKERRQ(ierr); 57 ierr = ISLocalToGlobalMappingDestroy(&b->mapping);CHKERRQ(ierr); 58 ierr = PetscFree(A->data);CHKERRQ(ierr); 59 ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr); 60 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "MatMult_IS" 66 PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y) 67 { 68 PetscErrorCode ierr; 69 Mat_IS *is = (Mat_IS*)A->data; 70 PetscScalar zero = 0.0; 71 72 PetscFunctionBegin; 73 /* scatter the global vector x into the local work vector */ 74 ierr = VecScatterBegin(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 75 ierr = VecScatterEnd(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 76 77 /* multiply the local matrix */ 78 ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr); 79 80 /* scatter product back into global memory */ 81 ierr = VecSet(y,zero);CHKERRQ(ierr); 82 ierr = VecScatterBegin(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 83 ierr = VecScatterEnd(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 84 PetscFunctionReturn(0); 85 } 86 87 #undef __FUNCT__ 88 #define __FUNCT__ "MatMultAdd_IS" 89 static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 90 { 91 Vec temp_vec; 92 PetscErrorCode ierr; 93 94 PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 95 if (v3 != v2) { 96 ierr = MatMult(A,v1,v3);CHKERRQ(ierr); 97 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 98 } else { 99 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 100 ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr); 101 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 102 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 103 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 104 } 105 PetscFunctionReturn(0); 106 } 107 108 #undef __FUNCT__ 109 #define __FUNCT__ "MatMultTranspose_IS" 110 PetscErrorCode MatMultTranspose_IS(Mat A,Vec x,Vec y) 111 { 112 Mat_IS *is = (Mat_IS*)A->data; 113 PetscErrorCode ierr; 114 115 PetscFunctionBegin; /* y = A' * x */ 116 /* scatter the global vector x into the local work vector */ 117 ierr = VecScatterBegin(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 118 ierr = VecScatterEnd(is->ctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 119 120 /* multiply the local matrix */ 121 ierr = MatMultTranspose(is->A,is->x,is->y);CHKERRQ(ierr); 122 123 /* scatter product back into global vector */ 124 ierr = VecSet(y,0);CHKERRQ(ierr); 125 ierr = VecScatterBegin(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 126 ierr = VecScatterEnd(is->ctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 127 PetscFunctionReturn(0); 128 } 129 130 #undef __FUNCT__ 131 #define __FUNCT__ "MatMultTransposeAdd_IS" 132 PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3) 133 { 134 Vec temp_vec; 135 PetscErrorCode ierr; 136 137 PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 138 if (v3 != v2) { 139 ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr); 140 ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr); 141 } else { 142 ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr); 143 ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr); 144 ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr); 145 ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr); 146 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr); 147 } 148 PetscFunctionReturn(0); 149 } 150 151 #undef __FUNCT__ 152 #define __FUNCT__ "MatView_IS" 153 PetscErrorCode MatView_IS(Mat A,PetscViewer viewer) 154 { 155 Mat_IS *a = (Mat_IS*)A->data; 156 PetscErrorCode ierr; 157 PetscViewer sviewer; 158 159 PetscFunctionBegin; 160 ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 161 ierr = MatView(a->A,sviewer);CHKERRQ(ierr); 162 ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 163 PetscFunctionReturn(0); 164 } 165 166 #undef __FUNCT__ 167 #define __FUNCT__ "MatSetLocalToGlobalMapping_IS" 168 PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping) 169 { 170 PetscErrorCode ierr; 171 PetscInt n,bs; 172 Mat_IS *is = (Mat_IS*)A->data; 173 IS from,to; 174 Vec global; 175 176 PetscFunctionBegin; 177 PetscCheckSameComm(A,1,rmapping,2); 178 if (rmapping != cmapping) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_INCOMP,"MATIS requires the row and column mappings to be identical"); 179 if (is->mapping) { /* Currenly destroys the objects that will be created by this routine. Is there anything else that should be checked? */ 180 ierr = ISLocalToGlobalMappingDestroy(&is->mapping);CHKERRQ(ierr); 181 ierr = VecDestroy(&is->x);CHKERRQ(ierr); 182 ierr = VecDestroy(&is->y);CHKERRQ(ierr); 183 ierr = VecScatterDestroy(&is->ctx);CHKERRQ(ierr); 184 } 185 ierr = PetscObjectReference((PetscObject)rmapping);CHKERRQ(ierr); 186 ierr = ISLocalToGlobalMappingDestroy(&is->mapping);CHKERRQ(ierr); 187 is->mapping = rmapping; 188 /* 189 ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr); 190 ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr); 191 */ 192 193 /* Create the local matrix A */ 194 ierr = ISLocalToGlobalMappingGetSize(rmapping,&n);CHKERRQ(ierr); 195 ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr); 196 ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr); 197 ierr = MatSetSizes(is->A,n,n,n,n);CHKERRQ(ierr); 198 ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr); 199 ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr); 200 ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr); 201 ierr = MatSetFromOptions(is->A);CHKERRQ(ierr); 202 203 /* Create the local work vectors */ 204 ierr = VecCreate(PETSC_COMM_SELF,&is->x);CHKERRQ(ierr); 205 ierr = VecSetBlockSize(is->x,bs);CHKERRQ(ierr); 206 ierr = VecSetSizes(is->x,n,n);CHKERRQ(ierr); 207 ierr = VecSetOptionsPrefix(is->x,((PetscObject)A)->prefix);CHKERRQ(ierr); 208 ierr = VecAppendOptionsPrefix(is->x,"is_");CHKERRQ(ierr); 209 ierr = VecSetFromOptions(is->x);CHKERRQ(ierr); 210 ierr = VecDuplicate(is->x,&is->y);CHKERRQ(ierr); 211 212 /* setup the global to local scatter */ 213 ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&to);CHKERRQ(ierr); 214 ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr); 215 ierr = MatGetVecs(A,&global,NULL);CHKERRQ(ierr); 216 ierr = VecScatterCreate(global,from,is->x,to,&is->ctx);CHKERRQ(ierr); 217 ierr = VecDestroy(&global);CHKERRQ(ierr); 218 ierr = ISDestroy(&to);CHKERRQ(ierr); 219 ierr = ISDestroy(&from);CHKERRQ(ierr); 220 PetscFunctionReturn(0); 221 } 222 223 #undef __FUNCT__ 224 #define __FUNCT__ "MatSetValues_IS" 225 PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv) 226 { 227 Mat_IS *is = (Mat_IS*)mat->data; 228 PetscInt rows_l[2048],cols_l[2048]; 229 PetscErrorCode ierr; 230 231 PetscFunctionBegin; 232 #if defined(PETSC_USE_DEBUG) 233 if (m > 2048 || n > 2048) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= 2048: they are %D %D",m,n); 234 #endif 235 ierr = ISG2LMapApply(is->mapping,m,rows,rows_l);CHKERRQ(ierr); 236 ierr = ISG2LMapApply(is->mapping,n,cols,cols_l);CHKERRQ(ierr); 237 ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr); 238 PetscFunctionReturn(0); 239 } 240 241 #undef ISG2LMapSetUp 242 #undef ISG2LMapApply 243 244 #undef __FUNCT__ 245 #define __FUNCT__ "MatSetValuesLocal_IS" 246 PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 247 { 248 PetscErrorCode ierr; 249 Mat_IS *is = (Mat_IS*)A->data; 250 251 PetscFunctionBegin; 252 ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 253 PetscFunctionReturn(0); 254 } 255 256 #undef __FUNCT__ 257 #define __FUNCT__ "MatSetValuesBlockedLocal_IS" 258 PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv) 259 { 260 PetscErrorCode ierr; 261 Mat_IS *is = (Mat_IS*)A->data; 262 263 PetscFunctionBegin; 264 ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr); 265 PetscFunctionReturn(0); 266 } 267 268 #undef __FUNCT__ 269 #define __FUNCT__ "MatZeroRows_IS" 270 PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 271 { 272 Mat_IS *is = (Mat_IS*)A->data; 273 PetscInt n_l = 0, *rows_l = NULL; 274 PetscErrorCode ierr; 275 276 PetscFunctionBegin; 277 if (x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support"); 278 if (n) { 279 ierr = PetscMalloc(n*sizeof(PetscInt),&rows_l);CHKERRQ(ierr); 280 ierr = ISGlobalToLocalMappingApply(is->mapping,IS_GTOLM_DROP,n,rows,&n_l,rows_l);CHKERRQ(ierr); 281 } 282 ierr = MatZeroRowsLocal(A,n_l,rows_l,diag,x,b);CHKERRQ(ierr); 283 ierr = PetscFree(rows_l);CHKERRQ(ierr); 284 PetscFunctionReturn(0); 285 } 286 287 #undef __FUNCT__ 288 #define __FUNCT__ "MatZeroRowsLocal_IS" 289 PetscErrorCode MatZeroRowsLocal_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 290 { 291 Mat_IS *is = (Mat_IS*)A->data; 292 PetscErrorCode ierr; 293 PetscInt i; 294 PetscScalar *array; 295 296 PetscFunctionBegin; 297 if (x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support"); 298 { 299 /* 300 Set up is->x as a "counting vector". This is in order to MatMult_IS 301 work properly in the interface nodes. 302 */ 303 Vec counter; 304 PetscScalar one=1.0, zero=0.0; 305 ierr = MatGetVecs(A,&counter,NULL);CHKERRQ(ierr); 306 ierr = VecSet(counter,zero);CHKERRQ(ierr); 307 ierr = VecSet(is->x,one);CHKERRQ(ierr); 308 ierr = VecScatterBegin(is->ctx,is->x,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 309 ierr = VecScatterEnd (is->ctx,is->x,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 310 ierr = VecScatterBegin(is->ctx,counter,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 311 ierr = VecScatterEnd (is->ctx,counter,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 312 ierr = VecDestroy(&counter);CHKERRQ(ierr); 313 } 314 if (!n) { 315 is->pure_neumann = PETSC_TRUE; 316 } else { 317 is->pure_neumann = PETSC_FALSE; 318 319 ierr = VecGetArray(is->x,&array);CHKERRQ(ierr); 320 ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr); 321 for (i=0; i<n; i++) { 322 ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr); 323 } 324 ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 325 ierr = MatAssemblyEnd (is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 326 ierr = VecRestoreArray(is->x,&array);CHKERRQ(ierr); 327 } 328 PetscFunctionReturn(0); 329 } 330 331 #undef __FUNCT__ 332 #define __FUNCT__ "MatAssemblyBegin_IS" 333 PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type) 334 { 335 Mat_IS *is = (Mat_IS*)A->data; 336 PetscErrorCode ierr; 337 338 PetscFunctionBegin; 339 ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr); 340 PetscFunctionReturn(0); 341 } 342 343 #undef __FUNCT__ 344 #define __FUNCT__ "MatAssemblyEnd_IS" 345 PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type) 346 { 347 Mat_IS *is = (Mat_IS*)A->data; 348 PetscErrorCode ierr; 349 350 PetscFunctionBegin; 351 ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr); 352 PetscFunctionReturn(0); 353 } 354 355 #undef __FUNCT__ 356 #define __FUNCT__ "MatISGetLocalMat_IS" 357 PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local) 358 { 359 Mat_IS *is = (Mat_IS*)mat->data; 360 361 PetscFunctionBegin; 362 *local = is->A; 363 PetscFunctionReturn(0); 364 } 365 366 #undef __FUNCT__ 367 #define __FUNCT__ "MatISGetLocalMat" 368 /*@ 369 MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 370 371 Input Parameter: 372 . mat - the matrix 373 374 Output Parameter: 375 . local - the local matrix usually MATSEQAIJ 376 377 Level: advanced 378 379 Notes: 380 This can be called if you have precomputed the nonzero structure of the 381 matrix and want to provide it to the inner matrix object to improve the performance 382 of the MatSetValues() operation. 383 384 .seealso: MATIS 385 @*/ 386 PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local) 387 { 388 PetscErrorCode ierr; 389 390 PetscFunctionBegin; 391 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 392 PetscValidPointer(local,2); 393 ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr); 394 PetscFunctionReturn(0); 395 } 396 397 #undef __FUNCT__ 398 #define __FUNCT__ "MatISSetLocalMat_IS" 399 PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local) 400 { 401 Mat_IS *is = (Mat_IS*)mat->data; 402 PetscInt nrows,ncols,orows,ocols; 403 PetscErrorCode ierr; 404 405 PetscFunctionBegin; 406 if (is->A) { 407 ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr); 408 ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr); 409 if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %dx%d (you passed a %dx%d matrix)\n",orows,ocols,nrows,ncols); 410 } 411 ierr = PetscObjectReference((PetscObject)local);CHKERRQ(ierr); 412 ierr = MatDestroy(&is->A);CHKERRQ(ierr); 413 is->A = local; 414 PetscFunctionReturn(0); 415 } 416 417 #undef __FUNCT__ 418 #define __FUNCT__ "MatISSetLocalMat" 419 /*@ 420 MatISSetLocalMat - Set the local matrix stored inside a MATIS matrix. 421 422 Input Parameter: 423 . mat - the matrix 424 . local - the local matrix usually MATSEQAIJ 425 426 Output Parameter: 427 428 Level: advanced 429 430 Notes: 431 This can be called if you have precomputed the local matrix and 432 want to provide it to the matrix object MATIS. 433 434 .seealso: MATIS 435 @*/ 436 PetscErrorCode MatISSetLocalMat(Mat mat,Mat local) 437 { 438 PetscErrorCode ierr; 439 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 442 ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr); 443 PetscFunctionReturn(0); 444 } 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "MatZeroEntries_IS" 448 PetscErrorCode MatZeroEntries_IS(Mat A) 449 { 450 Mat_IS *a = (Mat_IS*)A->data; 451 PetscErrorCode ierr; 452 453 PetscFunctionBegin; 454 ierr = MatZeroEntries(a->A);CHKERRQ(ierr); 455 PetscFunctionReturn(0); 456 } 457 458 #undef __FUNCT__ 459 #define __FUNCT__ "MatScale_IS" 460 PetscErrorCode MatScale_IS(Mat A,PetscScalar a) 461 { 462 Mat_IS *is = (Mat_IS*)A->data; 463 PetscErrorCode ierr; 464 465 PetscFunctionBegin; 466 ierr = MatScale(is->A,a);CHKERRQ(ierr); 467 PetscFunctionReturn(0); 468 } 469 470 #undef __FUNCT__ 471 #define __FUNCT__ "MatGetDiagonal_IS" 472 PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 473 { 474 Mat_IS *is = (Mat_IS*)A->data; 475 PetscErrorCode ierr; 476 477 PetscFunctionBegin; 478 /* get diagonal of the local matrix */ 479 ierr = MatGetDiagonal(is->A,is->x);CHKERRQ(ierr); 480 481 /* scatter diagonal back into global vector */ 482 ierr = VecSet(v,0);CHKERRQ(ierr); 483 ierr = VecScatterBegin(is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 484 ierr = VecScatterEnd (is->ctx,is->x,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 485 PetscFunctionReturn(0); 486 } 487 488 #undef __FUNCT__ 489 #define __FUNCT__ "MatSetOption_IS" 490 PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg) 491 { 492 Mat_IS *a = (Mat_IS*)A->data; 493 PetscErrorCode ierr; 494 495 PetscFunctionBegin; 496 ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 497 PetscFunctionReturn(0); 498 } 499 500 #undef __FUNCT__ 501 #define __FUNCT__ "MatCreateIS" 502 /*@ 503 MatCreateIS - Creates a "process" unassmembled matrix, it is assembled on each 504 process but not across processes. 505 506 Input Parameters: 507 + comm - MPI communicator that will share the matrix 508 . bs - local and global block size of the matrix 509 . m,n,M,N - local and/or global sizes of the the left and right vector used in matrix vector products 510 - map - mapping that defines the global number for each local number 511 512 Output Parameter: 513 . A - the resulting matrix 514 515 Level: advanced 516 517 Notes: See MATIS for more details 518 m and n are NOT related to the size of the map, they are the size of the part of the vector owned 519 by that process. m + nghosts (or n + nghosts) is the length of map since map maps all local points 520 plus the ghost points to global indices. 521 522 .seealso: MATIS, MatSetLocalToGlobalMapping() 523 @*/ 524 PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping map,Mat *A) 525 { 526 PetscErrorCode ierr; 527 528 PetscFunctionBegin; 529 ierr = MatCreate(comm,A);CHKERRQ(ierr); 530 ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr); 531 ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 532 ierr = MatSetType(*A,MATIS);CHKERRQ(ierr); 533 ierr = MatSetUp(*A);CHKERRQ(ierr); 534 ierr = MatSetLocalToGlobalMapping(*A,map,map);CHKERRQ(ierr); 535 PetscFunctionReturn(0); 536 } 537 538 /*MC 539 MATIS - MATIS = "is" - A matrix type to be used for using the Neumann-Neumann type preconditioners. 540 This stores the matrices in globally unassembled form. Each processor 541 assembles only its local Neumann problem and the parallel matrix vector 542 product is handled "implicitly". 543 544 Operations Provided: 545 + MatMult() 546 . MatMultAdd() 547 . MatMultTranspose() 548 . MatMultTransposeAdd() 549 . MatZeroEntries() 550 . MatSetOption() 551 . MatZeroRows() 552 . MatZeroRowsLocal() 553 . MatSetValues() 554 . MatSetValuesLocal() 555 . MatScale() 556 . MatGetDiagonal() 557 - MatSetLocalToGlobalMapping() 558 559 Options Database Keys: 560 . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 561 562 Notes: Options prefix for the inner matrix are given by -is_mat_xxx 563 564 You must call MatSetLocalToGlobalMapping() before using this matrix type. 565 566 You can do matrix preallocation on the local matrix after you obtain it with 567 MatISGetLocalMat() 568 569 Level: advanced 570 571 .seealso: PC, MatISGetLocalMat(), MatSetLocalToGlobalMapping() 572 573 M*/ 574 575 #undef __FUNCT__ 576 #define __FUNCT__ "MatCreate_IS" 577 PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 578 { 579 PetscErrorCode ierr; 580 Mat_IS *b; 581 582 PetscFunctionBegin; 583 ierr = PetscNewLog(A,Mat_IS,&b);CHKERRQ(ierr); 584 A->data = (void*)b; 585 ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 586 587 A->ops->mult = MatMult_IS; 588 A->ops->multadd = MatMultAdd_IS; 589 A->ops->multtranspose = MatMultTranspose_IS; 590 A->ops->multtransposeadd = MatMultTransposeAdd_IS; 591 A->ops->destroy = MatDestroy_IS; 592 A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 593 A->ops->setvalues = MatSetValues_IS; 594 A->ops->setvalueslocal = MatSetValuesLocal_IS; 595 A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 596 A->ops->zerorows = MatZeroRows_IS; 597 A->ops->zerorowslocal = MatZeroRowsLocal_IS; 598 A->ops->assemblybegin = MatAssemblyBegin_IS; 599 A->ops->assemblyend = MatAssemblyEnd_IS; 600 A->ops->view = MatView_IS; 601 A->ops->zeroentries = MatZeroEntries_IS; 602 A->ops->scale = MatScale_IS; 603 A->ops->getdiagonal = MatGetDiagonal_IS; 604 A->ops->setoption = MatSetOption_IS; 605 A->ops->ishermitian = MatIsHermitian_IS; 606 A->ops->issymmetric = MatIsSymmetric_IS; 607 608 ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr); 609 ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr); 610 611 b->A = 0; 612 b->ctx = 0; 613 b->x = 0; 614 b->y = 0; 615 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr); 616 ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr); 617 ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr); 618 PetscFunctionReturn(0); 619 } 620