xref: /petsc/src/mat/utils/gcreate.c (revision e08b1d6d0faae6eca507e20c9d3498f81719d047)
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   PetscTryTypeMethod(B,setfromoptions,PetscOptionsObject);
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((PetscObject)B,PetscOptionsObject));
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   /*
380      free all the interior data structures from mat
381      cannot use PetscUseTypeMethod(A,destroy); because compiler
382      thinks it may print NULL type_name and name
383   */
384   PetscTryTypeMethod(A,destroy);
385 
386   PetscCall(PetscFree(A->defaultvectype));
387   PetscCall(PetscLayoutDestroy(&A->rmap));
388   PetscCall(PetscLayoutDestroy(&A->cmap));
389   PetscCall(PetscFunctionListDestroy(&((PetscObject)A)->qlist));
390   PetscCall(PetscObjectListDestroy(&((PetscObject)A)->olist));
391   PetscCall(PetscComposedQuantitiesDestroy((PetscObject)A));
392 
393   /* copy C over to A */
394   PetscCall(PetscFree(A->factorprefix));
395   PetscCall(PetscMemcpy(A,*C,sizeof(struct _p_Mat)));
396 
397   /* return the parts of A we saved */
398   ((PetscObject)A)->bops[0]   = Abops;
399   A->ops[0]                   = Aops;
400   ((PetscObject)A)->refct     = refct;
401   ((PetscObject)A)->type_name = mtype;
402   ((PetscObject)A)->name      = mname;
403   ((PetscObject)A)->prefix    = mprefix;
404   ((PetscObject)A)->state     = state + 1;
405   A->product                  = product;
406   A->redundant                = redundant;
407 
408   /* since these two are copied into A we do not want them destroyed in C */
409   ((PetscObject)*C)->qlist = NULL;
410   ((PetscObject)*C)->olist = NULL;
411 
412   PetscCall(PetscHeaderDestroy(C));
413   PetscFunctionReturn(0);
414 }
415 /*
416         Replace A's header with that of C; the C object is then destroyed
417 
418         This is essentially code moved from MatDestroy()
419 
420         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
421 
422         Used in DM hence is declared PETSC_EXTERN
423 */
424 PETSC_EXTERN PetscErrorCode MatHeaderReplace(Mat A,Mat *C)
425 {
426   PetscInt         refct;
427   PetscObjectState state;
428   struct _p_Mat    buffer;
429   MatStencilInfo   stencil;
430 
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
433   PetscValidHeaderSpecific(*C,MAT_CLASSID,2);
434   if (A == *C) PetscFunctionReturn(0);
435   PetscCheckSameComm(A,1,*C,2);
436   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);
437 
438   /* swap C and A */
439   refct   = ((PetscObject)A)->refct;
440   state   = ((PetscObject)A)->state;
441   stencil = A->stencil;
442   PetscCall(PetscMemcpy(&buffer,A,sizeof(struct _p_Mat)));
443   PetscCall(PetscMemcpy(A,*C,sizeof(struct _p_Mat)));
444   PetscCall(PetscMemcpy(*C,&buffer,sizeof(struct _p_Mat)));
445   ((PetscObject)A)->refct = refct;
446   ((PetscObject)A)->state = state + 1;
447   A->stencil              = stencil;
448 
449   ((PetscObject)*C)->refct = 1;
450   PetscCall(MatShellSetOperation(*C,MATOP_DESTROY,(void(*)(void))NULL));
451   PetscCall(MatDestroy(C));
452   PetscFunctionReturn(0);
453 }
454 
455 /*@
456      MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
457 
458    Logically collective on Mat
459 
460    Input Parameters:
461 +   A - the matrix
462 -   flg - bind to the CPU if value of PETSC_TRUE
463 
464    Level: intermediate
465 
466 .seealso: `MatBoundToCPU()`
467 @*/
468 PetscErrorCode MatBindToCPU(Mat A,PetscBool flg)
469 {
470   PetscFunctionBegin;
471   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
472   PetscValidLogicalCollectiveBool(A,flg,2);
473 #if defined(PETSC_HAVE_DEVICE)
474   if (A->boundtocpu == flg) PetscFunctionReturn(0);
475   A->boundtocpu = flg;
476   PetscTryTypeMethod(A,bindtocpu,flg);
477 #endif
478   PetscFunctionReturn(0);
479 }
480 
481 /*@
482      MatBoundToCPU - query if a matrix is bound to the CPU
483 
484    Input Parameter:
485 .   A - the matrix
486 
487    Output Parameter:
488 .   flg - the logical flag
489 
490    Level: intermediate
491 
492 .seealso: `MatBindToCPU()`
493 @*/
494 PetscErrorCode MatBoundToCPU(Mat A,PetscBool *flg)
495 {
496   PetscFunctionBegin;
497   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
498   PetscValidBoolPointer(flg,2);
499 #if defined(PETSC_HAVE_DEVICE)
500   *flg = A->boundtocpu;
501 #else
502   *flg = PETSC_TRUE;
503 #endif
504   PetscFunctionReturn(0);
505 }
506 
507 PetscErrorCode MatSetValuesCOO_Basic(Mat A,const PetscScalar coo_v[],InsertMode imode)
508 {
509   IS             is_coo_i,is_coo_j;
510   const PetscInt *coo_i,*coo_j;
511   PetscInt       n,n_i,n_j;
512   PetscScalar    zero = 0.;
513 
514   PetscFunctionBegin;
515   PetscCall(PetscObjectQuery((PetscObject)A,"__PETSc_coo_i",(PetscObject*)&is_coo_i));
516   PetscCall(PetscObjectQuery((PetscObject)A,"__PETSc_coo_j",(PetscObject*)&is_coo_j));
517   PetscCheck(is_coo_i,PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_i IS");
518   PetscCheck(is_coo_j,PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_j IS");
519   PetscCall(ISGetLocalSize(is_coo_i,&n_i));
520   PetscCall(ISGetLocalSize(is_coo_j,&n_j));
521   PetscCheck(n_i == n_j,PETSC_COMM_SELF,PETSC_ERR_COR,"Wrong local size %" PetscInt_FMT " != %" PetscInt_FMT,n_i,n_j);
522   PetscCall(ISGetIndices(is_coo_i,&coo_i));
523   PetscCall(ISGetIndices(is_coo_j,&coo_j));
524   if (imode != ADD_VALUES) {
525     PetscCall(MatZeroEntries(A));
526   }
527   for (n = 0; n < n_i; n++) {
528     PetscCall(MatSetValue(A,coo_i[n],coo_j[n],coo_v ? coo_v[n] : zero,ADD_VALUES));
529   }
530   PetscCall(ISRestoreIndices(is_coo_i,&coo_i));
531   PetscCall(ISRestoreIndices(is_coo_j,&coo_j));
532   PetscFunctionReturn(0);
533 }
534 
535 PetscErrorCode MatSetPreallocationCOO_Basic(Mat A,PetscCount ncoo,const PetscInt coo_i[],const PetscInt coo_j[])
536 {
537   Mat            preallocator;
538   IS             is_coo_i,is_coo_j;
539   PetscScalar    zero = 0.0;
540 
541   PetscFunctionBegin;
542   PetscCall(PetscLayoutSetUp(A->rmap));
543   PetscCall(PetscLayoutSetUp(A->cmap));
544   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&preallocator));
545   PetscCall(MatSetType(preallocator,MATPREALLOCATOR));
546   PetscCall(MatSetSizes(preallocator,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
547   PetscCall(MatSetLayouts(preallocator,A->rmap,A->cmap));
548   PetscCall(MatSetUp(preallocator));
549   for (PetscCount n = 0; n < ncoo; n++) {
550     PetscCall(MatSetValue(preallocator,coo_i[n],coo_j[n],zero,INSERT_VALUES));
551   }
552   PetscCall(MatAssemblyBegin(preallocator,MAT_FINAL_ASSEMBLY));
553   PetscCall(MatAssemblyEnd(preallocator,MAT_FINAL_ASSEMBLY));
554   PetscCall(MatPreallocatorPreallocate(preallocator,PETSC_TRUE,A));
555   PetscCall(MatDestroy(&preallocator));
556   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);
557   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_i,PETSC_COPY_VALUES,&is_coo_i));
558   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_j,PETSC_COPY_VALUES,&is_coo_j));
559   PetscCall(PetscObjectCompose((PetscObject)A,"__PETSc_coo_i",(PetscObject)is_coo_i));
560   PetscCall(PetscObjectCompose((PetscObject)A,"__PETSc_coo_j",(PetscObject)is_coo_j));
561   PetscCall(ISDestroy(&is_coo_i));
562   PetscCall(ISDestroy(&is_coo_j));
563   PetscFunctionReturn(0);
564 }
565 
566 /*@C
567    MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries with global indices
568 
569    Collective on Mat
570 
571    Input Parameters:
572 +  A - matrix being preallocated
573 .  ncoo - number of entries
574 .  coo_i - row indices
575 -  coo_j - column indices
576 
577    Level: beginner
578 
579    Notes:
580    The indices coo_i and coo_j may be modified within this function. The caller should not rely on them
581    having any specific value after this function returns. The arrays can be freed or reused immediately
582    after this function returns.
583 
584    Entries can be repeated, see MatSetValuesCOO(). Entries with negative row or column indices are allowed
585    but will be ignored. The corresponding entries in MatSetValuesCOO() will be ignored too. Remote entries
586    are allowed and will be properly added or inserted to the matrix, unless the matrix option MAT_IGNORE_OFF_PROC_ENTRIES
587    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.
588 
589 .seealso: `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOOLocal()`, `DMSetMatrixPreallocateSkip()`
590 @*/
591 PetscErrorCode MatSetPreallocationCOO(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])
592 {
593   PetscErrorCode (*f)(Mat,PetscCount,const PetscInt[],const PetscInt[]) = NULL;
594 
595   PetscFunctionBegin;
596   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
597   PetscValidType(A,1);
598   if (ncoo) PetscValidIntPointer(coo_i,3);
599   if (ncoo) PetscValidIntPointer(coo_j,4);
600   PetscCall(PetscLayoutSetUp(A->rmap));
601   PetscCall(PetscLayoutSetUp(A->cmap));
602   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatSetPreallocationCOO_C",&f));
603 
604   PetscCall(PetscLogEventBegin(MAT_PreallCOO,A,0,0,0));
605   if (f) {
606     PetscCall((*f)(A,ncoo,coo_i,coo_j));
607   } else { /* allow fallback, very slow */
608     PetscCall(MatSetPreallocationCOO_Basic(A,ncoo,coo_i,coo_j));
609   }
610   PetscCall(PetscLogEventEnd(MAT_PreallCOO,A,0,0,0));
611   A->preallocated = PETSC_TRUE;
612   A->nonzerostate++;
613   PetscFunctionReturn(0);
614 }
615 
616 /*@C
617    MatSetPreallocationCOOLocal - set preallocation for matrices using a coordinate format of the entries with local indices
618 
619    Collective on Mat
620 
621    Input Parameters:
622 +  A - matrix being preallocated
623 .  ncoo - number of entries
624 .  coo_i - row indices (local numbering; may be modified)
625 -  coo_j - column indices (local numbering; may be modified)
626 
627    Level: beginner
628 
629    Notes:
630    The local indices are translated using the local to global mapping, thus MatSetLocalToGlobalMapping() must have been
631    called prior to this function.
632 
633    The indices coo_i and coo_j may be modified within this function. They might be translated to corresponding global
634    indices, but the caller should not rely on them having any specific value after this function returns. The arrays
635    can be freed or reused immediately after this function returns.
636 
637    Entries can be repeated, see MatSetValuesCOO(). Entries with negative row or column indices are allowed
638    but will be ignored. The corresponding entries in MatSetValuesCOO() will be ignored too. Remote entries
639    are allowed and will be properly added or inserted to the matrix.
640 
641 .seealso: `MatSetValuesCOO()`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatSeqBAIJSetPreallocation()`, `MatMPIBAIJSetPreallocation()`, `MatSeqSBAIJSetPreallocation()`, `MatMPISBAIJSetPreallocation()`, `MatSetPreallocationCOO()`, `DMSetMatrixPreallocateSkip()`
642 @*/
643 PetscErrorCode MatSetPreallocationCOOLocal(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])
644 {
645   PetscErrorCode (*f)(Mat,PetscCount,PetscInt[],PetscInt[]) = NULL;
646 
647   PetscFunctionBegin;
648   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
649   PetscValidType(A,1);
650   if (ncoo) PetscValidIntPointer(coo_i,3);
651   if (ncoo) PetscValidIntPointer(coo_j,4);
652   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);
653   PetscCall(PetscLayoutSetUp(A->rmap));
654   PetscCall(PetscLayoutSetUp(A->cmap));
655 
656   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",&f));
657   if (f) {
658     PetscCall((*f)(A,ncoo,coo_i,coo_j));
659     A->nonzerostate++;
660   } else {
661     ISLocalToGlobalMapping ltog_row,ltog_col;
662     PetscCall(MatGetLocalToGlobalMapping(A,&ltog_row,&ltog_col));
663     if (ltog_row) PetscCall(ISLocalToGlobalMappingApply(ltog_row,ncoo,coo_i,coo_i));
664     if (ltog_col) PetscCall(ISLocalToGlobalMappingApply(ltog_col,ncoo,coo_j,coo_j));
665     PetscCall(MatSetPreallocationCOO(A,ncoo,coo_i,coo_j));
666   }
667   A->preallocated = PETSC_TRUE;
668   PetscFunctionReturn(0);
669 }
670 
671 /*@
672    MatSetValuesCOO - set values at once in a matrix preallocated using MatSetPreallocationCOO()
673 
674    Collective on Mat
675 
676    Input Parameters:
677 +  A - matrix being preallocated
678 .  coo_v - the matrix values (can be NULL)
679 -  imode - the insert mode
680 
681    Level: beginner
682 
683    Notes: The values must follow the order of the indices prescribed with MatSetPreallocationCOO() or MatSetPreallocationCOOLocal().
684           When repeated entries are specified in the COO indices the coo_v values are first properly summed, regardless of the value of imode.
685           The imode flag indicates if coo_v must be added to the current values of the matrix (ADD_VALUES) or overwritten (INSERT_VALUES).
686           MatAssemblyBegin() and MatAssemblyEnd() do not need to be called after this routine. It automatically handles the assembly process.
687 
688 .seealso: `MatSetPreallocationCOO()`, `MatSetPreallocationCOOLocal()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
689 @*/
690 PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
691 {
692   PetscErrorCode (*f)(Mat,const PetscScalar[],InsertMode) = NULL;
693 
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
696   PetscValidType(A,1);
697   MatCheckPreallocated(A,1);
698   PetscValidLogicalCollectiveEnum(A,imode,3);
699   PetscCall(PetscObjectQueryFunction((PetscObject)A,"MatSetValuesCOO_C",&f));
700   PetscCall(PetscLogEventBegin(MAT_SetVCOO,A,0,0,0));
701   if (f) {
702     PetscCall((*f)(A,coo_v,imode));
703   } else { /* allow fallback */
704     PetscCall(MatSetValuesCOO_Basic(A,coo_v,imode));
705   }
706   PetscCall(PetscLogEventEnd(MAT_SetVCOO,A,0,0,0));
707   PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
708   PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
709   PetscFunctionReturn(0);
710 }
711 
712 /*@
713    MatSetBindingPropagates - Sets whether the state of being bound to the CPU for a GPU matrix type propagates to child and some other associated objects
714 
715    Input Parameters:
716 +  A - the matrix
717 -  flg - flag indicating whether the boundtocpu flag should be propagated
718 
719    Level: developer
720 
721    Notes:
722    If the value of flg is set to true, the following will occur:
723 
724    MatCreateSubMatrices() and MatCreateRedundantMatrix() will bind created matrices to CPU if the input matrix is bound to the CPU.
725    MatCreateVecs() will bind created vectors to CPU if the input matrix is bound to the CPU.
726    The bindingpropagates flag itself is also propagated by the above routines.
727 
728    Developer Notes:
729    If the fine-scale DMDA has the -dm_bind_below option set to true, then DMCreateInterpolationScale() calls MatSetBindingPropagates()
730    on the restriction/interpolation operator to set the bindingpropagates flag to true.
731 
732 .seealso: `VecSetBindingPropagates()`, `MatGetBindingPropagates()`
733 @*/
734 PetscErrorCode MatSetBindingPropagates(Mat A,PetscBool flg)
735 {
736   PetscFunctionBegin;
737   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
738 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
739   A->bindingpropagates = flg;
740 #endif
741   PetscFunctionReturn(0);
742 }
743 
744 /*@
745    MatGetBindingPropagates - Gets whether the state of being bound to the CPU for a GPU matrix type propagates to child and some other associated objects
746 
747    Input Parameter:
748 .  A - the matrix
749 
750    Output Parameter:
751 .  flg - flag indicating whether the boundtocpu flag will be propagated
752 
753    Level: developer
754 
755 .seealso: `MatSetBindingPropagates()`
756 @*/
757 PetscErrorCode MatGetBindingPropagates(Mat A,PetscBool *flg)
758 {
759   PetscFunctionBegin;
760   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
761   PetscValidBoolPointer(flg,2);
762 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
763   *flg = A->bindingpropagates;
764 #else
765   *flg = PETSC_FALSE;
766 #endif
767   PetscFunctionReturn(0);
768 }
769