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