xref: /petsc/src/mat/utils/gcreate.c (revision 2fa40bb9206b96114faa7cb222621ec184d31cd2)
1 
2 #include <petsc/private/matimpl.h>       /*I "petscmat.h"  I*/
3 
4 PETSC_INTERN PetscErrorCode MatSetBlockSizes_Default(Mat mat,PetscInt rbs, PetscInt cbs)
5 {
6   PetscFunctionBegin;
7   if (!mat->preallocated) PetscFunctionReturn(0);
8   if (mat->rmap->bs > 0 && mat->rmap->bs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot change row block size %D to %D\n",mat->rmap->bs,rbs);
9   if (mat->cmap->bs > 0 && mat->cmap->bs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot change column block size %D to %D\n",mat->cmap->bs,cbs);
10   PetscFunctionReturn(0);
11 }
12 
13 PETSC_INTERN PetscErrorCode MatShift_Basic(Mat Y,PetscScalar a)
14 {
15   PetscErrorCode ierr;
16   PetscInt       i,start,end;
17   PetscScalar    alpha = a;
18   PetscBool      prevoption;
19 
20   PetscFunctionBegin;
21   ierr = MatGetOption(Y,MAT_NO_OFF_PROC_ENTRIES,&prevoption);CHKERRQ(ierr);
22   ierr = MatSetOption(Y,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
23   ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
24   for (i=start; i<end; i++) {
25     if (i < Y->cmap->N) {
26       ierr = MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES);CHKERRQ(ierr);
27     }
28   }
29   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31   ierr = MatSetOption(Y,MAT_NO_OFF_PROC_ENTRIES,prevoption);CHKERRQ(ierr);
32   PetscFunctionReturn(0);
33 }
34 
35 /*@
36    MatCreate - Creates a matrix where the type is determined
37    from either a call to MatSetType() or from the options database
38    with a call to MatSetFromOptions(). The default matrix type is
39    AIJ, using the routines MatCreateSeqAIJ() or MatCreateAIJ()
40    if you do not set a type in the options database. If you never
41    call MatSetType() or MatSetFromOptions() it will generate an
42    error when you try to use the matrix.
43 
44    Collective
45 
46    Input Parameter:
47 .  comm - MPI communicator
48 
49    Output Parameter:
50 .  A - the matrix
51 
52    Options Database Keys:
53 +    -mat_type seqaij   - AIJ type, uses MatCreateSeqAIJ()
54 .    -mat_type mpiaij   - AIJ type, uses MatCreateAIJ()
55 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
56 .    -mat_type mpidense - dense type, uses MatCreateDense()
57 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
58 -    -mat_type mpibaij  - block AIJ type, uses MatCreateBAIJ()
59 
60    Even More Options Database Keys:
61    See the manpages for particular formats (e.g., MatCreateSeqAIJ())
62    for additional format-specific options.
63 
64    Level: beginner
65 
66 .seealso: MatCreateSeqAIJ(), MatCreateAIJ(),
67           MatCreateSeqDense(), MatCreateDense(),
68           MatCreateSeqBAIJ(), MatCreateBAIJ(),
69           MatCreateSeqSBAIJ(), MatCreateSBAIJ(),
70           MatConvert()
71 @*/
72 PetscErrorCode  MatCreate(MPI_Comm comm,Mat *A)
73 {
74   Mat            B;
75   PetscErrorCode ierr;
76 
77   PetscFunctionBegin;
78   PetscValidPointer(A,2);
79 
80   *A = NULL;
81   ierr = MatInitializePackage();CHKERRQ(ierr);
82 
83   ierr = PetscHeaderCreate(B,MAT_CLASSID,"Mat","Matrix","Mat",comm,MatDestroy,MatView);CHKERRQ(ierr);
84   ierr = PetscLayoutCreate(comm,&B->rmap);CHKERRQ(ierr);
85   ierr = PetscLayoutCreate(comm,&B->cmap);CHKERRQ(ierr);
86   ierr = PetscStrallocpy(VECSTANDARD,&B->defaultvectype);CHKERRQ(ierr);
87 
88   B->congruentlayouts = PETSC_DECIDE;
89   B->preallocated     = PETSC_FALSE;
90 #if defined(PETSC_HAVE_DEVICE)
91   B->boundtocpu       = PETSC_TRUE;
92 #endif
93   *A                  = B;
94   PetscFunctionReturn(0);
95 }
96 
97 /*@
98    MatSetErrorIfFailure - Causes Mat to generate an error, for example a zero pivot, is detected.
99 
100    Logically Collective on Mat
101 
102    Input Parameters:
103 +  mat -  matrix obtained from MatCreate()
104 -  flg - PETSC_TRUE indicates you want the error generated
105 
106    Level: advanced
107 
108 .seealso: PCSetErrorIfFailure()
109 @*/
110 PetscErrorCode  MatSetErrorIfFailure(Mat mat,PetscBool flg)
111 {
112   PetscFunctionBegin;
113   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
114   PetscValidLogicalCollectiveBool(mat,flg,2);
115   mat->erroriffailure = flg;
116   PetscFunctionReturn(0);
117 }
118 
119 /*@
120   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
121 
122   Collective on Mat
123 
124   Input Parameters:
125 +  A - the matrix
126 .  m - number of local rows (or PETSC_DECIDE)
127 .  n - number of local columns (or PETSC_DECIDE)
128 .  M - number of global rows (or PETSC_DETERMINE)
129 -  N - number of global columns (or PETSC_DETERMINE)
130 
131    Notes:
132    m (n) and M (N) cannot be both PETSC_DECIDE
133    If one processor calls this with M (N) of PETSC_DECIDE then all processors must, otherwise the program will hang.
134 
135    If PETSC_DECIDE is not used for the arguments 'm' and 'n', then the
136    user must ensure that they are chosen to be compatible with the
137    vectors. To do this, one first considers the matrix-vector product
138    'y = A x'. The 'm' that is used in the above routine must match the
139    local size used in the vector creation routine VecCreateMPI() for 'y'.
140    Likewise, the 'n' used must match that used as the local size in
141    VecCreateMPI() for 'x'.
142 
143    You cannot change the sizes once they have been set.
144 
145    The sizes must be set before MatSetUp() or MatXXXSetPreallocation() is called.
146 
147   Level: beginner
148 
149 .seealso: MatGetSize(), PetscSplitOwnership()
150 @*/
151 PetscErrorCode  MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
152 {
153   PetscFunctionBegin;
154   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
155   PetscValidLogicalCollectiveInt(A,M,4);
156   PetscValidLogicalCollectiveInt(A,N,5);
157   if (M > 0 && m > M) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local row size %D cannot be larger than global row size %D",m,M);
158   if (N > 0 && n > N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local column size %D cannot be larger than global column size %D",n,N);
159   if ((A->rmap->n >= 0 && A->rmap->N >= 0) && (A->rmap->n != m || (M > 0 && A->rmap->N != M))) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change/reset row sizes to %D local %D global after previously setting them to %D local %D global",m,M,A->rmap->n,A->rmap->N);
160   if ((A->cmap->n >= 0 && A->cmap->N >= 0) && (A->cmap->n != n || (N > 0 && A->cmap->N != N))) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot change/reset column sizes to %D local %D global after previously setting them to %D local %D global",n,N,A->cmap->n,A->cmap->N);
161   A->rmap->n = m;
162   A->cmap->n = n;
163   A->rmap->N = M > -1 ? M : A->rmap->N;
164   A->cmap->N = N > -1 ? N : A->cmap->N;
165   PetscFunctionReturn(0);
166 }
167 
168 /*@
169    MatSetFromOptions - Creates a matrix where the type is determined
170    from the options database. Generates a parallel MPI matrix if the
171    communicator has more than one processor.  The default matrix type is
172    AIJ, using the routines MatCreateSeqAIJ() and MatCreateAIJ() if
173    you do not select a type in the options database.
174 
175    Collective on Mat
176 
177    Input Parameter:
178 .  A - the matrix
179 
180    Options Database Keys:
181 +    -mat_type seqaij   - AIJ type, uses MatCreateSeqAIJ()
182 .    -mat_type mpiaij   - AIJ type, uses MatCreateAIJ()
183 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
184 .    -mat_type mpidense - dense type, uses MatCreateDense()
185 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
186 -    -mat_type mpibaij  - block AIJ type, uses MatCreateBAIJ()
187 
188    Even More Options Database Keys:
189    See the manpages for particular formats (e.g., MatCreateSeqAIJ())
190    for additional format-specific options.
191 
192    Level: beginner
193 
194 .seealso: MatCreateSeqAIJ((), MatCreateAIJ(),
195           MatCreateSeqDense(), MatCreateDense(),
196           MatCreateSeqBAIJ(), MatCreateBAIJ(),
197           MatCreateSeqSBAIJ(), MatCreateSBAIJ(),
198           MatConvert()
199 @*/
200 PetscErrorCode  MatSetFromOptions(Mat B)
201 {
202   PetscErrorCode ierr;
203   const char     *deft = MATAIJ;
204   char           type[256];
205   PetscBool      flg,set;
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   /* process any options handlers added with PetscObjectAddOptionsHandler() */
252   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)B);CHKERRQ(ierr);
253   ierr = PetscOptionsEnd();CHKERRQ(ierr);
254   PetscFunctionReturn(0);
255 }
256 
257 /*@C
258    MatXAIJSetPreallocation - set preallocation for serial and parallel AIJ, BAIJ, and SBAIJ matrices and their unassembled versions.
259 
260    Collective on Mat
261 
262    Input Parameters:
263 +  A - matrix being preallocated
264 .  bs - block size
265 .  dnnz - number of nonzero column blocks per block row of diagonal part of parallel matrix
266 .  onnz - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
267 .  dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
268 -  onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
269 
270    Level: beginner
271 
272 .seealso: MatSeqAIJSetPreallocation(), MatMPIAIJSetPreallocation(), MatSeqBAIJSetPreallocation(), MatMPIBAIJSetPreallocation(), MatSeqSBAIJSetPreallocation(), MatMPISBAIJSetPreallocation(),
273           PetscSplitOwnership()
274 @*/
275 PetscErrorCode MatXAIJSetPreallocation(Mat A,PetscInt bs,const PetscInt dnnz[],const PetscInt onnz[],const PetscInt dnnzu[],const PetscInt onnzu[])
276 {
277   PetscErrorCode ierr;
278   PetscInt       cbs;
279   void           (*aij)(void);
280   void           (*is)(void);
281   void           (*hyp)(void) = NULL;
282 
283   PetscFunctionBegin;
284   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
285     ierr = MatSetBlockSize(A,bs);CHKERRQ(ierr);
286   }
287   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
288   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
289   ierr = MatGetBlockSizes(A,&bs,&cbs);CHKERRQ(ierr);
290   /* these routines assumes bs == cbs, this should be checked somehow */
291   ierr = MatSeqBAIJSetPreallocation(A,bs,0,dnnz);CHKERRQ(ierr);
292   ierr = MatMPIBAIJSetPreallocation(A,bs,0,dnnz,0,onnz);CHKERRQ(ierr);
293   ierr = MatSeqSBAIJSetPreallocation(A,bs,0,dnnzu);CHKERRQ(ierr);
294   ierr = MatMPISBAIJSetPreallocation(A,bs,0,dnnzu,0,onnzu);CHKERRQ(ierr);
295   /*
296     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
297     good before going on with it.
298   */
299   ierr = PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
300   ierr = PetscObjectQueryFunction((PetscObject)A,"MatISSetPreallocation_C",&is);CHKERRQ(ierr);
301 #if defined(PETSC_HAVE_HYPRE)
302   ierr = PetscObjectQueryFunction((PetscObject)A,"MatHYPRESetPreallocation_C",&hyp);CHKERRQ(ierr);
303 #endif
304   if (!aij && !is && !hyp) {
305     ierr = PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
306   }
307   if (aij || is || hyp) {
308     if (bs == cbs && bs == 1) {
309       ierr = MatSeqAIJSetPreallocation(A,0,dnnz);CHKERRQ(ierr);
310       ierr = MatMPIAIJSetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
311       ierr = MatISSetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
312 #if defined(PETSC_HAVE_HYPRE)
313       ierr = MatHYPRESetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
314 #endif
315     } else { /* Convert block-row precallocation to scalar-row */
316       PetscInt i,m,*sdnnz,*sonnz;
317       ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr);
318       ierr = PetscMalloc2((!!dnnz)*m,&sdnnz,(!!onnz)*m,&sonnz);CHKERRQ(ierr);
319       for (i=0; i<m; i++) {
320         if (dnnz) sdnnz[i] = dnnz[i/bs] * cbs;
321         if (onnz) sonnz[i] = onnz[i/bs] * cbs;
322       }
323       ierr = MatSeqAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL);CHKERRQ(ierr);
324       ierr = MatMPIAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
325       ierr = MatISSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
326 #if defined(PETSC_HAVE_HYPRE)
327       ierr = MatHYPRESetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
328 #endif
329       ierr = PetscFree2(sdnnz,sonnz);CHKERRQ(ierr);
330     }
331   }
332   PetscFunctionReturn(0);
333 }
334 
335 /*
336         Merges some information from Cs header to A; the C object is then destroyed
337 
338         This is somewhat different from MatHeaderReplace() it would be nice to merge the code
339 */
340 PetscErrorCode MatHeaderMerge(Mat A,Mat *C)
341 {
342   PetscErrorCode ierr;
343   PetscInt       refct;
344   PetscOps       Abops;
345   struct _MatOps Aops;
346   char           *mtype,*mname,*mprefix;
347   Mat_Product    *product;
348 
349   PetscFunctionBegin;
350   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
351   PetscValidHeaderSpecific(*C,MAT_CLASSID,2);
352   if (A == *C) PetscFunctionReturn(0);
353   PetscCheckSameComm(A,1,*C,2);
354   /* save the parts of A we need */
355   Abops = ((PetscObject)A)->bops[0];
356   Aops  = A->ops[0];
357   refct = ((PetscObject)A)->refct;
358   mtype = ((PetscObject)A)->type_name;
359   mname = ((PetscObject)A)->name;
360   mprefix = ((PetscObject)A)->prefix;
361   product = A->product;
362 
363   /* zero these so the destroy below does not free them */
364   ((PetscObject)A)->type_name = NULL;
365   ((PetscObject)A)->name      = NULL;
366 
367   /* free all the interior data structures from mat */
368   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
369 
370   ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
371   ierr = PetscLayoutDestroy(&A->rmap);CHKERRQ(ierr);
372   ierr = PetscLayoutDestroy(&A->cmap);CHKERRQ(ierr);
373   ierr = PetscFunctionListDestroy(&((PetscObject)A)->qlist);CHKERRQ(ierr);
374   ierr = PetscObjectListDestroy(&((PetscObject)A)->olist);CHKERRQ(ierr);
375 
376   /* copy C over to A */
377   ierr = PetscMemcpy(A,*C,sizeof(struct _p_Mat));CHKERRQ(ierr);
378 
379   /* return the parts of A we saved */
380   ((PetscObject)A)->bops[0]   = Abops;
381   A->ops[0]                   = Aops;
382   ((PetscObject)A)->refct     = refct;
383   ((PetscObject)A)->type_name = mtype;
384   ((PetscObject)A)->name      = mname;
385   ((PetscObject)A)->prefix    = mprefix;
386   A->product                  = product;
387 
388   /* since these two are copied into A we do not want them destroyed in C */
389   ((PetscObject)*C)->qlist = NULL;
390   ((PetscObject)*C)->olist = NULL;
391 
392   ierr = PetscHeaderDestroy(C);CHKERRQ(ierr);
393   PetscFunctionReturn(0);
394 }
395 /*
396         Replace A's header with that of C; the C object is then destroyed
397 
398         This is essentially code moved from MatDestroy()
399 
400         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
401 
402         Used in DM hence is declared PETSC_EXTERN
403 */
404 PETSC_EXTERN PetscErrorCode MatHeaderReplace(Mat A,Mat *C)
405 {
406   PetscErrorCode   ierr;
407   PetscInt         refct;
408   PetscObjectState state;
409   struct _p_Mat    buffer;
410   MatStencilInfo   stencil;
411 
412   PetscFunctionBegin;
413   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
414   PetscValidHeaderSpecific(*C,MAT_CLASSID,2);
415   if (A == *C) PetscFunctionReturn(0);
416   PetscCheckSameComm(A,1,*C,2);
417   if (((PetscObject)*C)->refct != 1) SETERRQ1(PetscObjectComm((PetscObject)C),PETSC_ERR_ARG_WRONGSTATE,"Object C has refct %D > 1, would leave hanging reference",((PetscObject)*C)->refct);
418 
419   /* swap C and A */
420   refct   = ((PetscObject)A)->refct;
421   state   = ((PetscObject)A)->state;
422   stencil = A->stencil;
423   ierr  = PetscMemcpy(&buffer,A,sizeof(struct _p_Mat));CHKERRQ(ierr);
424   ierr  = PetscMemcpy(A,*C,sizeof(struct _p_Mat));CHKERRQ(ierr);
425   ierr  = PetscMemcpy(*C,&buffer,sizeof(struct _p_Mat));CHKERRQ(ierr);
426   ((PetscObject)A)->refct   = refct;
427   ((PetscObject)A)->state   = state + 1;
428   A->stencil                = stencil;
429 
430   ((PetscObject)*C)->refct = 1;
431   ierr = MatShellSetOperation(*C,MATOP_DESTROY,(void(*)(void))NULL);CHKERRQ(ierr);
432   ierr = MatDestroy(C);CHKERRQ(ierr);
433   PetscFunctionReturn(0);
434 }
435 
436 /*@
437      MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
438 
439    Logically collective on Mat
440 
441    Input Parameters:
442 +   A - the matrix
443 -   flg - bind to the CPU if value of PETSC_TRUE
444 
445    Level: intermediate
446 
447 .seealso: MatBoundToCPU()
448 @*/
449 PetscErrorCode MatBindToCPU(Mat A,PetscBool flg)
450 {
451   PetscFunctionBegin;
452   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
453   PetscValidLogicalCollectiveBool(A,flg,2);
454 #if defined(PETSC_HAVE_DEVICE)
455   if (A->boundtocpu == flg) PetscFunctionReturn(0);
456   A->boundtocpu = flg;
457   if (A->ops->bindtocpu) {
458     PetscErrorCode ierr;
459     ierr = (*A->ops->bindtocpu)(A,flg);CHKERRQ(ierr);
460   }
461 #endif
462   PetscFunctionReturn(0);
463 }
464 
465 /*@
466      MatBoundToCPU - query if a matrix is bound to the CPU
467 
468    Input Parameter:
469 .   A - the matrix
470 
471    Output Parameter:
472 .   flg - the logical flag
473 
474    Level: intermediate
475 
476 .seealso: MatBindToCPU()
477 @*/
478 PetscErrorCode MatBoundToCPU(Mat A,PetscBool *flg)
479 {
480   PetscFunctionBegin;
481   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
482   PetscValidPointer(flg,2);
483 #if defined(PETSC_HAVE_DEVICE)
484   *flg = A->boundtocpu;
485 #else
486   *flg = PETSC_TRUE;
487 #endif
488   PetscFunctionReturn(0);
489 }
490 
491 PetscErrorCode MatSetValuesCOO_Basic(Mat A,const PetscScalar coo_v[],InsertMode imode)
492 {
493   IS             is_coo_i,is_coo_j;
494   const PetscInt *coo_i,*coo_j;
495   PetscInt       n,n_i,n_j;
496   PetscScalar    zero = 0.;
497   PetscErrorCode ierr;
498 
499   PetscFunctionBegin;
500   ierr = PetscObjectQuery((PetscObject)A,"__PETSc_coo_i",(PetscObject*)&is_coo_i);CHKERRQ(ierr);
501   ierr = PetscObjectQuery((PetscObject)A,"__PETSc_coo_j",(PetscObject*)&is_coo_j);CHKERRQ(ierr);
502   if (!is_coo_i) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_i IS");
503   if (!is_coo_j) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_j IS");
504   ierr = ISGetLocalSize(is_coo_i,&n_i);CHKERRQ(ierr);
505   ierr = ISGetLocalSize(is_coo_j,&n_j);CHKERRQ(ierr);
506   if (n_i != n_j)  SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_COR,"Wrong local size %D != %D",n_i,n_j);
507   ierr = ISGetIndices(is_coo_i,&coo_i);CHKERRQ(ierr);
508   ierr = ISGetIndices(is_coo_j,&coo_j);CHKERRQ(ierr);
509   if (imode != ADD_VALUES) {
510     ierr = MatZeroEntries(A);CHKERRQ(ierr);
511   }
512   for (n = 0; n < n_i; n++) {
513     ierr = MatSetValue(A,coo_i[n],coo_j[n],coo_v ? coo_v[n] : zero,ADD_VALUES);CHKERRQ(ierr);
514   }
515   ierr = ISRestoreIndices(is_coo_i,&coo_i);CHKERRQ(ierr);
516   ierr = ISRestoreIndices(is_coo_j,&coo_j);CHKERRQ(ierr);
517   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
518   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
519   PetscFunctionReturn(0);
520 }
521 
522 PetscErrorCode MatSetPreallocationCOO_Basic(Mat A,PetscInt ncoo,const PetscInt coo_i[],const PetscInt coo_j[])
523 {
524   Mat            preallocator;
525   IS             is_coo_i,is_coo_j;
526   PetscScalar    zero = 0.0;
527   PetscInt       n;
528   PetscErrorCode ierr;
529 
530   PetscFunctionBegin;
531   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
532   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
533   ierr = MatCreate(PetscObjectComm((PetscObject)A),&preallocator);CHKERRQ(ierr);
534   ierr = MatSetType(preallocator,MATPREALLOCATOR);CHKERRQ(ierr);
535   ierr = MatSetSizes(preallocator,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
536   ierr = MatSetLayouts(preallocator,A->rmap,A->cmap);CHKERRQ(ierr);
537   ierr = MatSetUp(preallocator);CHKERRQ(ierr);
538   for (n = 0; n < ncoo; n++) {
539     ierr = MatSetValue(preallocator,coo_i[n],coo_j[n],zero,INSERT_VALUES);CHKERRQ(ierr);
540   }
541   ierr = MatAssemblyBegin(preallocator,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
542   ierr = MatAssemblyEnd(preallocator,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
543   ierr = MatPreallocatorPreallocate(preallocator,PETSC_TRUE,A);CHKERRQ(ierr);
544   ierr = MatDestroy(&preallocator);CHKERRQ(ierr);
545   ierr = ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_i,PETSC_COPY_VALUES,&is_coo_i);CHKERRQ(ierr);
546   ierr = ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_j,PETSC_COPY_VALUES,&is_coo_j);CHKERRQ(ierr);
547   ierr = PetscObjectCompose((PetscObject)A,"__PETSc_coo_i",(PetscObject)is_coo_i);CHKERRQ(ierr);
548   ierr = PetscObjectCompose((PetscObject)A,"__PETSc_coo_j",(PetscObject)is_coo_j);CHKERRQ(ierr);
549   ierr = ISDestroy(&is_coo_i);CHKERRQ(ierr);
550   ierr = ISDestroy(&is_coo_j);CHKERRQ(ierr);
551   PetscFunctionReturn(0);
552 }
553 
554 /*@
555    MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries
556 
557    Collective on Mat
558 
559    Input Parameters:
560 +  A - matrix being preallocated
561 .  ncoo - number of entries in the locally owned part of the parallel matrix
562 .  coo_i - row indices
563 -  coo_j - column indices
564 
565    Level: beginner
566 
567    Notes: Entries can be repeated, see MatSetValuesCOO(). Currently optimized for cuSPARSE matrices only.
568 
569 .seealso: MatSetValuesCOO(), MatSeqAIJSetPreallocation(), MatMPIAIJSetPreallocation(), MatSeqBAIJSetPreallocation(), MatMPIBAIJSetPreallocation(), MatSeqSBAIJSetPreallocation(), MatMPISBAIJSetPreallocation()
570 @*/
571 PetscErrorCode MatSetPreallocationCOO(Mat A,PetscInt ncoo,const PetscInt coo_i[],const PetscInt coo_j[])
572 {
573   PetscErrorCode (*f)(Mat,PetscInt,const PetscInt[],const PetscInt[]) = NULL;
574   PetscErrorCode ierr;
575 
576   PetscFunctionBegin;
577   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
578   PetscValidType(A,1);
579   if (ncoo) PetscValidIntPointer(coo_i,3);
580   if (ncoo) PetscValidIntPointer(coo_j,4);
581   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
582   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
583   if (PetscDefined(USE_DEBUG)) {
584     PetscInt i;
585     for (i = 0; i < ncoo; i++) {
586       if (coo_i[i] < A->rmap->rstart || coo_i[i] >= A->rmap->rend) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid row index %D! Must be in [%D,%D)",coo_i[i],A->rmap->rstart,A->rmap->rend);
587       if (coo_j[i] < 0 || coo_j[i] >= A->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Invalid col index %D! Must be in [0,%D)",coo_j[i],A->cmap->N);
588     }
589   }
590   ierr = PetscObjectQueryFunction((PetscObject)A,"MatSetPreallocationCOO_C",&f);CHKERRQ(ierr);
591   ierr = PetscLogEventBegin(MAT_PreallCOO,A,0,0,0);CHKERRQ(ierr);
592   if (f) {
593     ierr = (*f)(A,ncoo,coo_i,coo_j);CHKERRQ(ierr);
594   } else { /* allow fallback, very slow */
595     ierr = MatSetPreallocationCOO_Basic(A,ncoo,coo_i,coo_j);CHKERRQ(ierr);
596   }
597   ierr = PetscLogEventEnd(MAT_PreallCOO,A,0,0,0);CHKERRQ(ierr);
598   PetscFunctionReturn(0);
599 }
600 
601 /*@
602    MatSetValuesCOO - set values at once in a matrix preallocated using MatSetPreallocationCOO()
603 
604    Collective on Mat
605 
606    Input Parameters:
607 +  A - matrix being preallocated
608 .  coo_v - the matrix values (can be NULL)
609 -  imode - the insert mode
610 
611    Level: beginner
612 
613    Notes: The values must follow the order of the indices prescribed with MatSetPreallocationCOO().
614           When repeated entries are specified in the COO indices the coo_v values are first properly summed.
615           The imode flag indicates if coo_v must be added to the current values of the matrix (ADD_VALUES) or overwritten (INSERT_VALUES).
616           Currently optimized for cuSPARSE matrices only.
617           Passing coo_v == NULL is equivalent to passing an array of zeros.
618 
619 .seealso: MatSetPreallocationCOO(), InsertMode, INSERT_VALUES, ADD_VALUES
620 @*/
621 PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
622 {
623   PetscErrorCode (*f)(Mat,const PetscScalar[],InsertMode) = NULL;
624   PetscErrorCode ierr;
625 
626   PetscFunctionBegin;
627   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
628   PetscValidType(A,1);
629   MatCheckPreallocated(A,1);
630   PetscValidLogicalCollectiveEnum(A,imode,3);
631   ierr = PetscObjectQueryFunction((PetscObject)A,"MatSetValuesCOO_C",&f);CHKERRQ(ierr);
632   ierr = PetscLogEventBegin(MAT_SetVCOO,A,0,0,0);CHKERRQ(ierr);
633   if (f) {
634     ierr = (*f)(A,coo_v,imode);CHKERRQ(ierr);
635   } else { /* allow fallback */
636     ierr = MatSetValuesCOO_Basic(A,coo_v,imode);CHKERRQ(ierr);
637   }
638   ierr = PetscLogEventEnd(MAT_SetVCOO,A,0,0,0);CHKERRQ(ierr);
639   ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr);
640   PetscFunctionReturn(0);
641 }
642