1 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 2 3 PETSC_INTERN PetscErrorCode MatSetBlockSizes_Default(Mat mat,PetscInt rbs, PetscInt cbs) 4 { 5 PetscFunctionBegin; 6 if (!mat->preallocated) PetscFunctionReturn(0); 7 PetscCheck(mat->rmap->bs <= 0 || mat->rmap->bs == rbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot change row block size %" PetscInt_FMT " to %" PetscInt_FMT,mat->rmap->bs,rbs); 8 PetscCheck(mat->cmap->bs <= 0 || mat->cmap->bs == cbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot change column block size %" PetscInt_FMT " to %" PetscInt_FMT,mat->cmap->bs,cbs); 9 PetscFunctionReturn(0); 10 } 11 12 PETSC_INTERN PetscErrorCode MatShift_Basic(Mat Y,PetscScalar a) 13 { 14 PetscInt i,start,end; 15 PetscScalar alpha = a; 16 PetscBool prevoption; 17 18 PetscFunctionBegin; 19 PetscCall(MatGetOption(Y,MAT_NO_OFF_PROC_ENTRIES,&prevoption)); 20 PetscCall(MatSetOption(Y,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE)); 21 PetscCall(MatGetOwnershipRange(Y,&start,&end)); 22 for (i=start; i<end; i++) { 23 if (i < Y->cmap->N) { 24 PetscCall(MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES)); 25 } 26 } 27 PetscCall(MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY)); 28 PetscCall(MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY)); 29 PetscCall(MatSetOption(Y,MAT_NO_OFF_PROC_ENTRIES,prevoption)); 30 PetscFunctionReturn(0); 31 } 32 33 /*@ 34 MatCreate - Creates a matrix where the type is determined 35 from either a call to MatSetType() or from the options database 36 with a call to MatSetFromOptions(). The default matrix type is 37 AIJ, using the routines MatCreateSeqAIJ() or MatCreateAIJ() 38 if you do not set a type in the options database. If you never 39 call MatSetType() or MatSetFromOptions() it will generate an 40 error when you try to use the matrix. 41 42 Collective 43 44 Input Parameter: 45 . comm - MPI communicator 46 47 Output Parameter: 48 . A - the matrix 49 50 Options Database Keys: 51 + -mat_type seqaij - AIJ type, uses MatCreateSeqAIJ() 52 . -mat_type mpiaij - AIJ type, uses MatCreateAIJ() 53 . -mat_type seqdense - dense type, uses MatCreateSeqDense() 54 . -mat_type mpidense - dense type, uses MatCreateDense() 55 . -mat_type seqbaij - block AIJ type, uses MatCreateSeqBAIJ() 56 - -mat_type mpibaij - block AIJ type, uses MatCreateBAIJ() 57 58 Even More Options Database Keys: 59 See the manpages for particular formats (e.g., MatCreateSeqAIJ()) 60 for additional format-specific options. 61 62 Level: beginner 63 64 .seealso: `MatCreateSeqAIJ()`, `MatCreateAIJ()`, 65 `MatCreateSeqDense()`, `MatCreateDense()`, 66 `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, 67 `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`, 68 `MatConvert()` 69 @*/ 70 PetscErrorCode MatCreate(MPI_Comm comm,Mat *A) 71 { 72 Mat B; 73 74 PetscFunctionBegin; 75 PetscValidPointer(A,2); 76 77 *A = NULL; 78 PetscCall(MatInitializePackage()); 79 80 PetscCall(PetscHeaderCreate(B,MAT_CLASSID,"Mat","Matrix","Mat",comm,MatDestroy,MatView)); 81 PetscCall(PetscLayoutCreate(comm,&B->rmap)); 82 PetscCall(PetscLayoutCreate(comm,&B->cmap)); 83 PetscCall(PetscStrallocpy(VECSTANDARD,&B->defaultvectype)); 84 85 B->symmetric = PETSC_BOOL3_UNKNOWN; 86 B->hermitian = PETSC_BOOL3_UNKNOWN; 87 B->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 88 B->spd = PETSC_BOOL3_UNKNOWN; 89 B->symmetry_eternal = PETSC_FALSE; 90 B->structural_symmetry_eternal = PETSC_FALSE; 91 92 B->congruentlayouts = PETSC_DECIDE; 93 B->preallocated = PETSC_FALSE; 94 #if defined(PETSC_HAVE_DEVICE) 95 B->boundtocpu = PETSC_TRUE; 96 #endif 97 *A = B; 98 PetscFunctionReturn(0); 99 } 100 101 /*@ 102 MatSetErrorIfFailure - Causes Mat to generate an error, for example a zero pivot, is detected. 103 104 Logically Collective on Mat 105 106 Input Parameters: 107 + mat - matrix obtained from MatCreate() 108 - flg - PETSC_TRUE indicates you want the error generated 109 110 Level: advanced 111 112 .seealso: `PCSetErrorIfFailure()` 113 @*/ 114 PetscErrorCode MatSetErrorIfFailure(Mat mat,PetscBool flg) 115 { 116 PetscFunctionBegin; 117 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 118 PetscValidLogicalCollectiveBool(mat,flg,2); 119 mat->erroriffailure = flg; 120 PetscFunctionReturn(0); 121 } 122 123 /*@ 124 MatSetSizes - Sets the local and global sizes, and checks to determine compatibility 125 126 Collective on Mat 127 128 Input Parameters: 129 + A - the matrix 130 . m - number of local rows (or PETSC_DECIDE) 131 . n - number of local columns (or PETSC_DECIDE) 132 . M - number of global rows (or PETSC_DETERMINE) 133 - N - number of global columns (or PETSC_DETERMINE) 134 135 Notes: 136 m (n) and M (N) cannot be both PETSC_DECIDE 137 If one processor calls this with M (N) of PETSC_DECIDE then all processors must, otherwise the program will hang. 138 139 If PETSC_DECIDE is not used for the arguments 'm' and 'n', then the 140 user must ensure that they are chosen to be compatible with the 141 vectors. To do this, one first considers the matrix-vector product 142 'y = A x'. The 'm' that is used in the above routine must match the 143 local size used in the vector creation routine VecCreateMPI() for 'y'. 144 Likewise, the 'n' used must match that used as the local size in 145 VecCreateMPI() for 'x'. 146 147 You cannot change the sizes once they have been set. 148 149 The sizes must be set before MatSetUp() or MatXXXSetPreallocation() is called. 150 151 Level: beginner 152 153 .seealso: `MatGetSize()`, `PetscSplitOwnership()` 154 @*/ 155 PetscErrorCode MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N) 156 { 157 PetscFunctionBegin; 158 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 159 PetscValidLogicalCollectiveInt(A,M,4); 160 PetscValidLogicalCollectiveInt(A,N,5); 161 PetscCheck(M <= 0 || m <= M,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local row size %" PetscInt_FMT " cannot be larger than global row size %" PetscInt_FMT,m,M); 162 PetscCheck(N <= 0 || n <= N,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local column size %" PetscInt_FMT " cannot be larger than global column size %" PetscInt_FMT,n,N); 163 PetscCheck((A->rmap->n < 0 || A->rmap->N < 0) || (A->rmap->n == m && (M <= 0 || A->rmap->N == M)),PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change/reset row sizes to %" PetscInt_FMT " local %" PetscInt_FMT " global after previously setting them to %" PetscInt_FMT " local %" PetscInt_FMT " global",m,M,A->rmap->n,A->rmap->N); 164 PetscCheck((A->cmap->n < 0 || A->cmap->N < 0) || (A->cmap->n == n && (N <= 0 || A->cmap->N == N)),PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change/reset column sizes to %" PetscInt_FMT " local %" PetscInt_FMT " global after previously setting them to %" PetscInt_FMT " local %" PetscInt_FMT " global",n,N,A->cmap->n,A->cmap->N); 165 A->rmap->n = m; 166 A->cmap->n = n; 167 A->rmap->N = M > -1 ? M : A->rmap->N; 168 A->cmap->N = N > -1 ? N : A->cmap->N; 169 PetscFunctionReturn(0); 170 } 171 172 /*@ 173 MatSetFromOptions - Creates a matrix where the type is determined 174 from the options database. Generates a parallel MPI matrix if the 175 communicator has more than one processor. The default matrix type is 176 AIJ, using the routines MatCreateSeqAIJ() and MatCreateAIJ() if 177 you do not select a type in the options database. 178 179 Collective on Mat 180 181 Input Parameter: 182 . A - the matrix 183 184 Options Database Keys: 185 + -mat_type seqaij - AIJ type, uses MatCreateSeqAIJ() 186 . -mat_type mpiaij - AIJ type, uses MatCreateAIJ() 187 . -mat_type seqdense - dense type, uses MatCreateSeqDense() 188 . -mat_type mpidense - dense type, uses MatCreateDense() 189 . -mat_type seqbaij - block AIJ type, uses MatCreateSeqBAIJ() 190 - -mat_type mpibaij - block AIJ type, uses MatCreateBAIJ() 191 192 Even More Options Database Keys: 193 See the manpages for particular formats (e.g., MatCreateSeqAIJ()) 194 for additional format-specific options. 195 196 Level: beginner 197 198 .seealso: `MatCreateSeqAIJ(()`, `MatCreateAIJ()`, 199 `MatCreateSeqDense()`, `MatCreateDense()`, 200 `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, 201 `MatCreateSeqSBAIJ()`, `MatCreateSBAIJ()`, 202 `MatConvert()` 203 @*/ 204 PetscErrorCode MatSetFromOptions(Mat B) 205 { 206 const char *deft = MATAIJ; 207 char type[256]; 208 PetscBool flg,set; 209 PetscInt bind_below = 0; 210 211 PetscFunctionBegin; 212 PetscValidHeaderSpecific(B,MAT_CLASSID,1); 213 214 PetscObjectOptionsBegin((PetscObject)B); 215 216 if (B->rmap->bs < 0) { 217 PetscInt newbs = -1; 218 PetscCall(PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSetBlockSize",newbs,&newbs,&flg)); 219 if (flg) { 220 PetscCall(PetscLayoutSetBlockSize(B->rmap,newbs)); 221 PetscCall(PetscLayoutSetBlockSize(B->cmap,newbs)); 222 } 223 } 224 225 PetscCall(PetscOptionsFList("-mat_type","Matrix type","MatSetType",MatList,deft,type,256,&flg)); 226 if (flg) { 227 PetscCall(MatSetType(B,type)); 228 } else if (!((PetscObject)B)->type_name) { 229 PetscCall(MatSetType(B,deft)); 230 } 231 232 PetscCall(PetscOptionsName("-mat_is_symmetric","Checks if mat is symmetric on MatAssemblyEnd()","MatIsSymmetric",&B->checksymmetryonassembly)); 233 PetscCall(PetscOptionsReal("-mat_is_symmetric","Checks if mat is symmetric on MatAssemblyEnd()","MatIsSymmetric",B->checksymmetrytol,&B->checksymmetrytol,NULL)); 234 PetscCall(PetscOptionsBool("-mat_null_space_test","Checks if provided null space is correct in MatAssemblyEnd()","MatSetNullSpaceTest",B->checknullspaceonassembly,&B->checknullspaceonassembly,NULL)); 235 PetscCall(PetscOptionsBool("-mat_error_if_failure","Generate an error if an error occurs when factoring the matrix","MatSetErrorIfFailure",B->erroriffailure,&B->erroriffailure,NULL)); 236 237 if (B->ops->setfromoptions) PetscCall((*B->ops->setfromoptions)(PetscOptionsObject,B)); 238 239 flg = PETSC_FALSE; 240 PetscCall(PetscOptionsBool("-mat_new_nonzero_location_err","Generate an error if new nonzeros are created in the matrix structure (useful to test preallocation)","MatSetOption",flg,&flg,&set)); 241 if (set) PetscCall(MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,flg)); 242 flg = PETSC_FALSE; 243 PetscCall(PetscOptionsBool("-mat_new_nonzero_allocation_err","Generate an error if new nonzeros are allocated in the matrix structure (useful to test preallocation)","MatSetOption",flg,&flg,&set)); 244 if (set) PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,flg)); 245 flg = PETSC_FALSE; 246 PetscCall(PetscOptionsBool("-mat_ignore_zero_entries","For AIJ/IS matrices this will stop zero values from creating a zero location in the matrix","MatSetOption",flg,&flg,&set)); 247 if (set) PetscCall(MatSetOption(B,MAT_IGNORE_ZERO_ENTRIES,flg)); 248 249 flg = PETSC_FALSE; 250 PetscCall(PetscOptionsBool("-mat_form_explicit_transpose","Hint to form an explicit transpose for operations like MatMultTranspose","MatSetOption",flg,&flg,&set)); 251 if (set) PetscCall(MatSetOption(B,MAT_FORM_EXPLICIT_TRANSPOSE,flg)); 252 253 /* Bind to CPU if below a user-specified size threshold. 254 * This perhaps belongs in the options for the GPU Mat types, but MatBindToCPU() does nothing when called on non-GPU types, 255 * and putting it here makes is more maintainable than duplicating this for all. */ 256 PetscCall(PetscOptionsInt("-mat_bind_below","Set the size threshold (in local rows) below which the Mat is bound to the CPU","MatBindToCPU",bind_below,&bind_below,&flg)); 257 if (flg && B->rmap->n < bind_below) { 258 PetscCall(MatBindToCPU(B,PETSC_TRUE)); 259 } 260 261 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 262 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)B)); 263 PetscOptionsEnd(); 264 PetscFunctionReturn(0); 265 } 266 267 /*@C 268 MatXAIJSetPreallocation - set preallocation for serial and parallel AIJ, BAIJ, and SBAIJ matrices and their unassembled versions. 269 270 Collective on Mat 271 272 Input Parameters: 273 + A - matrix being preallocated 274 . bs - block size 275 . dnnz - number of nonzero column blocks per block row of diagonal part of parallel matrix 276 . onnz - number of nonzero column blocks per block row of off-diagonal part of parallel matrix 277 . dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix 278 - onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix 279 280 Level: beginner 281 282 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, 283 `PetscSplitOwnership()` 284 @*/ 285 PetscErrorCode MatXAIJSetPreallocation(Mat A,PetscInt bs,const PetscInt dnnz[],const PetscInt onnz[],const PetscInt dnnzu[],const PetscInt onnzu[]) 286 { 287 PetscInt cbs; 288 void (*aij)(void); 289 void (*is)(void); 290 void (*hyp)(void) = NULL; 291 292 PetscFunctionBegin; 293 if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */ 294 PetscCall(MatSetBlockSize(A,bs)); 295 } 296 PetscCall(PetscLayoutSetUp(A->rmap)); 297 PetscCall(PetscLayoutSetUp(A->cmap)); 298 PetscCall(MatGetBlockSizes(A,&bs,&cbs)); 299 /* these routines assumes bs == cbs, this should be checked somehow */ 300 PetscCall(MatSeqBAIJSetPreallocation(A,bs,0,dnnz)); 301 PetscCall(MatMPIBAIJSetPreallocation(A,bs,0,dnnz,0,onnz)); 302 PetscCall(MatSeqSBAIJSetPreallocation(A,bs,0,dnnzu)); 303 PetscCall(MatMPISBAIJSetPreallocation(A,bs,0,dnnzu,0,onnzu)); 304 /* 305 In general, we have to do extra work to preallocate for scalar (AIJ) or unassembled (IS) matrices so we check whether it will do any 306 good before going on with it. 307 */ 308 PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij)); 309 PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatISSetPreallocation_C",&is)); 310 #if defined(PETSC_HAVE_HYPRE) 311 PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatHYPRESetPreallocation_C",&hyp)); 312 #endif 313 if (!aij && !is && !hyp) { 314 PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij)); 315 } 316 if (aij || is || hyp) { 317 if (bs == cbs && bs == 1) { 318 PetscCall(MatSeqAIJSetPreallocation(A,0,dnnz)); 319 PetscCall(MatMPIAIJSetPreallocation(A,0,dnnz,0,onnz)); 320 PetscCall(MatISSetPreallocation(A,0,dnnz,0,onnz)); 321 #if defined(PETSC_HAVE_HYPRE) 322 PetscCall(MatHYPRESetPreallocation(A,0,dnnz,0,onnz)); 323 #endif 324 } else { /* Convert block-row precallocation to scalar-row */ 325 PetscInt i,m,*sdnnz,*sonnz; 326 PetscCall(MatGetLocalSize(A,&m,NULL)); 327 PetscCall(PetscMalloc2((!!dnnz)*m,&sdnnz,(!!onnz)*m,&sonnz)); 328 for (i=0; i<m; i++) { 329 if (dnnz) sdnnz[i] = dnnz[i/bs] * cbs; 330 if (onnz) sonnz[i] = onnz[i/bs] * cbs; 331 } 332 PetscCall(MatSeqAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL)); 333 PetscCall(MatMPIAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL)); 334 PetscCall(MatISSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL)); 335 #if defined(PETSC_HAVE_HYPRE) 336 PetscCall(MatHYPRESetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL)); 337 #endif 338 PetscCall(PetscFree2(sdnnz,sonnz)); 339 } 340 } 341 PetscFunctionReturn(0); 342 } 343 344 /* 345 Merges some information from Cs header to A; the C object is then destroyed 346 347 This is somewhat different from MatHeaderReplace() it would be nice to merge the code 348 */ 349 PetscErrorCode MatHeaderMerge(Mat A,Mat *C) 350 { 351 PetscInt refct; 352 PetscOps Abops; 353 struct _MatOps Aops; 354 char *mtype,*mname,*mprefix; 355 Mat_Product *product; 356 Mat_Redundant *redundant; 357 PetscObjectState state; 358 359 PetscFunctionBegin; 360 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 361 PetscValidHeaderSpecific(*C,MAT_CLASSID,2); 362 if (A == *C) PetscFunctionReturn(0); 363 PetscCheckSameComm(A,1,*C,2); 364 /* save the parts of A we need */ 365 Abops = ((PetscObject)A)->bops[0]; 366 Aops = A->ops[0]; 367 refct = ((PetscObject)A)->refct; 368 mtype = ((PetscObject)A)->type_name; 369 mname = ((PetscObject)A)->name; 370 state = ((PetscObject)A)->state; 371 mprefix = ((PetscObject)A)->prefix; 372 product = A->product; 373 redundant = A->redundant; 374 375 /* zero these so the destroy below does not free them */ 376 ((PetscObject)A)->type_name = NULL; 377 ((PetscObject)A)->name = NULL; 378 379 /* free all the interior data structures from mat */ 380 PetscCall((*A->ops->destroy)(A)); 381 382 PetscCall(PetscFree(A->defaultvectype)); 383 PetscCall(PetscLayoutDestroy(&A->rmap)); 384 PetscCall(PetscLayoutDestroy(&A->cmap)); 385 PetscCall(PetscFunctionListDestroy(&((PetscObject)A)->qlist)); 386 PetscCall(PetscObjectListDestroy(&((PetscObject)A)->olist)); 387 PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A)); 388 389 /* copy C over to A */ 390 PetscCall(PetscFree(A->factorprefix)); 391 PetscCall(PetscMemcpy(A,*C,sizeof(struct _p_Mat))); 392 393 /* return the parts of A we saved */ 394 ((PetscObject)A)->bops[0] = Abops; 395 A->ops[0] = Aops; 396 ((PetscObject)A)->refct = refct; 397 ((PetscObject)A)->type_name = mtype; 398 ((PetscObject)A)->name = mname; 399 ((PetscObject)A)->prefix = mprefix; 400 ((PetscObject)A)->state = state + 1; 401 A->product = product; 402 A->redundant = redundant; 403 404 /* since these two are copied into A we do not want them destroyed in C */ 405 ((PetscObject)*C)->qlist = NULL; 406 ((PetscObject)*C)->olist = NULL; 407 408 PetscCall(PetscHeaderDestroy(C)); 409 PetscFunctionReturn(0); 410 } 411 /* 412 Replace A's header with that of C; the C object is then destroyed 413 414 This is essentially code moved from MatDestroy() 415 416 This is somewhat different from MatHeaderMerge() it would be nice to merge the code 417 418 Used in DM hence is declared PETSC_EXTERN 419 */ 420 PETSC_EXTERN PetscErrorCode MatHeaderReplace(Mat A,Mat *C) 421 { 422 PetscInt refct; 423 PetscObjectState state; 424 struct _p_Mat buffer; 425 MatStencilInfo stencil; 426 427 PetscFunctionBegin; 428 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 429 PetscValidHeaderSpecific(*C,MAT_CLASSID,2); 430 if (A == *C) PetscFunctionReturn(0); 431 PetscCheckSameComm(A,1,*C,2); 432 PetscCheck(((PetscObject)*C)->refct == 1,PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Object C has refct %" PetscInt_FMT " > 1, would leave hanging reference",((PetscObject)*C)->refct); 433 434 /* swap C and A */ 435 refct = ((PetscObject)A)->refct; 436 state = ((PetscObject)A)->state; 437 stencil = A->stencil; 438 PetscCall(PetscMemcpy(&buffer,A,sizeof(struct _p_Mat))); 439 PetscCall(PetscMemcpy(A,*C,sizeof(struct _p_Mat))); 440 PetscCall(PetscMemcpy(*C,&buffer,sizeof(struct _p_Mat))); 441 ((PetscObject)A)->refct = refct; 442 ((PetscObject)A)->state = state + 1; 443 A->stencil = stencil; 444 445 ((PetscObject)*C)->refct = 1; 446 PetscCall(MatShellSetOperation(*C,MATOP_DESTROY,(void(*)(void))NULL)); 447 PetscCall(MatDestroy(C)); 448 PetscFunctionReturn(0); 449 } 450 451 /*@ 452 MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU 453 454 Logically collective on Mat 455 456 Input Parameters: 457 + A - the matrix 458 - flg - bind to the CPU if value of PETSC_TRUE 459 460 Level: intermediate 461 462 .seealso: `MatBoundToCPU()` 463 @*/ 464 PetscErrorCode MatBindToCPU(Mat A,PetscBool flg) 465 { 466 PetscFunctionBegin; 467 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 468 PetscValidLogicalCollectiveBool(A,flg,2); 469 #if defined(PETSC_HAVE_DEVICE) 470 if (A->boundtocpu == flg) PetscFunctionReturn(0); 471 A->boundtocpu = flg; 472 if (A->ops->bindtocpu) PetscCall((*A->ops->bindtocpu)(A,flg)); 473 #endif 474 PetscFunctionReturn(0); 475 } 476 477 /*@ 478 MatBoundToCPU - query if a matrix is bound to the CPU 479 480 Input Parameter: 481 . A - the matrix 482 483 Output Parameter: 484 . flg - the logical flag 485 486 Level: intermediate 487 488 .seealso: `MatBindToCPU()` 489 @*/ 490 PetscErrorCode MatBoundToCPU(Mat A,PetscBool *flg) 491 { 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 494 PetscValidBoolPointer(flg,2); 495 #if defined(PETSC_HAVE_DEVICE) 496 *flg = A->boundtocpu; 497 #else 498 *flg = PETSC_TRUE; 499 #endif 500 PetscFunctionReturn(0); 501 } 502 503 PetscErrorCode MatSetValuesCOO_Basic(Mat A,const PetscScalar coo_v[],InsertMode imode) 504 { 505 IS is_coo_i,is_coo_j; 506 const PetscInt *coo_i,*coo_j; 507 PetscInt n,n_i,n_j; 508 PetscScalar zero = 0.; 509 510 PetscFunctionBegin; 511 PetscCall(PetscObjectQuery((PetscObject)A,"__PETSc_coo_i",(PetscObject*)&is_coo_i)); 512 PetscCall(PetscObjectQuery((PetscObject)A,"__PETSc_coo_j",(PetscObject*)&is_coo_j)); 513 PetscCheck(is_coo_i,PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_i IS"); 514 PetscCheck(is_coo_j,PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_j IS"); 515 PetscCall(ISGetLocalSize(is_coo_i,&n_i)); 516 PetscCall(ISGetLocalSize(is_coo_j,&n_j)); 517 PetscCheck(n_i == n_j,PETSC_COMM_SELF,PETSC_ERR_COR,"Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT,n_i,n_j); 518 PetscCall(ISGetIndices(is_coo_i,&coo_i)); 519 PetscCall(ISGetIndices(is_coo_j,&coo_j)); 520 if (imode != ADD_VALUES) { 521 PetscCall(MatZeroEntries(A)); 522 } 523 for (n = 0; n < n_i; n++) { 524 PetscCall(MatSetValue(A,coo_i[n],coo_j[n],coo_v ? coo_v[n] : zero,ADD_VALUES)); 525 } 526 PetscCall(ISRestoreIndices(is_coo_i,&coo_i)); 527 PetscCall(ISRestoreIndices(is_coo_j,&coo_j)); 528 PetscFunctionReturn(0); 529 } 530 531 PetscErrorCode MatSetPreallocationCOO_Basic(Mat A,PetscCount ncoo,const PetscInt coo_i[],const PetscInt coo_j[]) 532 { 533 Mat preallocator; 534 IS is_coo_i,is_coo_j; 535 PetscScalar zero = 0.0; 536 537 PetscFunctionBegin; 538 PetscCall(PetscLayoutSetUp(A->rmap)); 539 PetscCall(PetscLayoutSetUp(A->cmap)); 540 PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&preallocator)); 541 PetscCall(MatSetType(preallocator,MATPREALLOCATOR)); 542 PetscCall(MatSetSizes(preallocator,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N)); 543 PetscCall(MatSetLayouts(preallocator,A->rmap,A->cmap)); 544 PetscCall(MatSetUp(preallocator)); 545 for (PetscCount n = 0; n < ncoo; n++) { 546 PetscCall(MatSetValue(preallocator,coo_i[n],coo_j[n],zero,INSERT_VALUES)); 547 } 548 PetscCall(MatAssemblyBegin(preallocator,MAT_FINAL_ASSEMBLY)); 549 PetscCall(MatAssemblyEnd(preallocator,MAT_FINAL_ASSEMBLY)); 550 PetscCall(MatPreallocatorPreallocate(preallocator,PETSC_TRUE,A)); 551 PetscCall(MatDestroy(&preallocator)); 552 PetscCheck(ncoo <= PETSC_MAX_INT,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support",ncoo); 553 PetscCall(ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_i,PETSC_COPY_VALUES,&is_coo_i)); 554 PetscCall(ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_j,PETSC_COPY_VALUES,&is_coo_j)); 555 PetscCall(PetscObjectCompose((PetscObject)A,"__PETSc_coo_i",(PetscObject)is_coo_i)); 556 PetscCall(PetscObjectCompose((PetscObject)A,"__PETSc_coo_j",(PetscObject)is_coo_j)); 557 PetscCall(ISDestroy(&is_coo_i)); 558 PetscCall(ISDestroy(&is_coo_j)); 559 PetscFunctionReturn(0); 560 } 561 562 /*@C 563 MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices 564 565 Collective on Mat 566 567 Input Parameters: 568 + A - matrix being preallocated 569 . ncoo - number of entries 570 . coo_i - row indices 571 - coo_j - column indices 572 573 Level: beginner 574 575 Notes: 576 Entries can be repeated, see MatSetValuesCOO(). Entries with negative row or column indices are allowed 577 but will be ignored. The corresponding entries in MatSetValuesCOO() will be ignored too. Remote entries 578 are allowed and will be properly added or inserted to the matrix, unless the matrix option MAT_IGNORE_OFF_PROC_ENTRIES 579 is set, in which case remote entries are ignored, or MAT_NO_OFF_PROC_ENTRIES is set, in which case an error will be generated. 580 581 The arrays coo_i and coo_j may be freed immediately after calling this function. 582 583 .seealso: `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`, `DMSetMatrixPreallocateSkip()` 584 @*/ 585 PetscErrorCode MatSetPreallocationCOO(Mat A,PetscCount ncoo,const PetscInt coo_i[],const PetscInt coo_j[]) 586 { 587 PetscErrorCode (*f)(Mat,PetscCount,const PetscInt[],const PetscInt[]) = NULL; 588 589 PetscFunctionBegin; 590 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 591 PetscValidType(A,1); 592 if (ncoo) PetscValidIntPointer(coo_i,3); 593 if (ncoo) PetscValidIntPointer(coo_j,4); 594 PetscCall(PetscLayoutSetUp(A->rmap)); 595 PetscCall(PetscLayoutSetUp(A->cmap)); 596 PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatSetPreallocationCOO_C",&f)); 597 598 PetscCall(PetscLogEventBegin(MAT_PreallCOO,A,0,0,0)); 599 if (f) { 600 PetscCall((*f)(A,ncoo,coo_i,coo_j)); 601 } else { /* allow fallback, very slow */ 602 PetscCall(MatSetPreallocationCOO_Basic(A,ncoo,coo_i,coo_j)); 603 } 604 PetscCall(PetscLogEventEnd(MAT_PreallCOO,A,0,0,0)); 605 A->preallocated = PETSC_TRUE; 606 A->nonzerostate++; 607 PetscFunctionReturn(0); 608 } 609 610 /*@C 611 MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices 612 613 Collective on Mat 614 615 Input Parameters: 616 + A - matrix being preallocated 617 . ncoo - number of entries 618 . coo_i - row indices (local numbering; may be modified) 619 - coo_j - column indices (local numbering; may be modified) 620 621 Level: beginner 622 623 Notes: 624 The local indices are translated using the local to global mapping, thus MatSetLocalToGlobalMapping() must have been 625 called prior to this function. 626 627 The indices coo_i and coo_j may be modified within this function. They might be translated to corresponding global 628 indices, but the caller should not rely on them having any specific value after this function returns. The arrays 629 can be freed or reused immediately after this function returns. 630 631 Entries can be repeated, see MatSetValuesCOO(). Entries with negative row or column indices are allowed 632 but will be ignored. The corresponding entries in MatSetValuesCOO() will be ignored too. Remote entries 633 are allowed and will be properly added or inserted to the matrix. 634 635 .seealso: `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`, `DMSetMatrixPreallocateSkip()` 636 @*/ 637 PetscErrorCode MatSetPreallocationCOOLocal(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[]) 638 { 639 PetscErrorCode (*f)(Mat,PetscCount,PetscInt[],PetscInt[]) = NULL; 640 641 PetscFunctionBegin; 642 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 643 PetscValidType(A,1); 644 if (ncoo) PetscValidIntPointer(coo_i,3); 645 if (ncoo) PetscValidIntPointer(coo_j,4); 646 PetscCheck(ncoo <= PETSC_MAX_INT,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support",ncoo); 647 PetscCall(PetscLayoutSetUp(A->rmap)); 648 PetscCall(PetscLayoutSetUp(A->cmap)); 649 650 PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",&f)); 651 if (f) { 652 PetscCall((*f)(A,ncoo,coo_i,coo_j)); 653 A->nonzerostate++; 654 } else { 655 ISLocalToGlobalMapping ltog_row,ltog_col; 656 PetscCall(MatGetLocalToGlobalMapping(A,<og_row,<og_col)); 657 if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row,ncoo,coo_i,coo_i)); 658 if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col,ncoo,coo_j,coo_j)); 659 PetscCall(MatSetPreallocationCOO(A,ncoo,coo_i,coo_j)); 660 } 661 A->preallocated = PETSC_TRUE; 662 PetscFunctionReturn(0); 663 } 664 665 /*@ 666 MatSetValuesCOO - set values at once in a matrix preallocated using MatSetPreallocationCOO() 667 668 Collective on Mat 669 670 Input Parameters: 671 + A - matrix being preallocated 672 . coo_v - the matrix values (can be NULL) 673 - imode - the insert mode 674 675 Level: beginner 676 677 Notes: The values must follow the order of the indices prescribed with MatSetPreallocationCOO() or MatSetPreallocationCOOLocal(). 678 When repeated entries are specified in the COO indices the coo_v values are first properly summed, regardless of the value of imode. 679 The imode flag indicates if coo_v must be added to the current values of the matrix (ADD_VALUES) or overwritten (INSERT_VALUES). 680 MatAssemblyBegin() and MatAssemblyEnd() do not need to be called after this routine. It automatically handles the assembly process. 681 682 .seealso: `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 683 @*/ 684 PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode) 685 { 686 PetscErrorCode (*f)(Mat,const PetscScalar[],InsertMode) = NULL; 687 688 PetscFunctionBegin; 689 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 690 PetscValidType(A,1); 691 MatCheckPreallocated(A,1); 692 PetscValidLogicalCollectiveEnum(A,imode,3); 693 PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatSetValuesCOO_C",&f)); 694 PetscCall(PetscLogEventBegin(MAT_SetVCOO,A,0,0,0)); 695 if (f) { 696 PetscCall((*f)(A,coo_v,imode)); 697 } else { /* allow fallback */ 698 PetscCall(MatSetValuesCOO_Basic(A,coo_v,imode)); 699 } 700 PetscCall(PetscLogEventEnd(MAT_SetVCOO,A,0,0,0)); 701 PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY)); 702 PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)); 703 PetscFunctionReturn(0); 704 } 705 706 /*@ 707 MatSetBindingPropagates - Sets whether the state of being bound to the CPU for a GPU matrix type propagates to child and some other associated objects 708 709 Input Parameters: 710 + A - the matrix 711 - flg - flag indicating whether the boundtocpu flag should be propagated 712 713 Level: developer 714 715 Notes: 716 If the value of flg is set to true, the following will occur: 717 718 MatCreateSubMatrices() and MatCreateRedundantMatrix() will bind created matrices to CPU if the input matrix is bound to the CPU. 719 MatCreateVecs() will bind created vectors to CPU if the input matrix is bound to the CPU. 720 The bindingpropagates flag itself is also propagated by the above routines. 721 722 Developer Notes: 723 If the fine-scale DMDA has the -dm_bind_below option set to true, then DMCreateInterpolationScale() calls MatSetBindingPropagates() 724 on the restriction/interpolation operator to set the bindingpropagates flag to true. 725 726 .seealso: `VecSetBindingPropagates()`, `MatGetBindingPropagates()` 727 @*/ 728 PetscErrorCode MatSetBindingPropagates(Mat A,PetscBool flg) 729 { 730 PetscFunctionBegin; 731 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 732 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 733 A->bindingpropagates = flg; 734 #endif 735 PetscFunctionReturn(0); 736 } 737 738 /*@ 739 MatGetBindingPropagates - Gets whether the state of being bound to the CPU for a GPU matrix type propagates to child and some other associated objects 740 741 Input Parameter: 742 . A - the matrix 743 744 Output Parameter: 745 . flg - flag indicating whether the boundtocpu flag will be propagated 746 747 Level: developer 748 749 .seealso: `MatSetBindingPropagates()` 750 @*/ 751 PetscErrorCode MatGetBindingPropagates(Mat A,PetscBool *flg) 752 { 753 PetscFunctionBegin; 754 PetscValidHeaderSpecific(A,MAT_CLASSID,1); 755 PetscValidBoolPointer(flg,2); 756 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) 757 *flg = A->bindingpropagates; 758 #else 759 *flg = PETSC_FALSE; 760 #endif 761 PetscFunctionReturn(0); 762 } 763