xref: /petsc/src/mat/utils/gcreate.c (revision 95a2cb335deee435f0b06953e4461b2237b5f64e)
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   *A                  = B;
91   PetscFunctionReturn(0);
92 }
93 
94 /*@
95    MatSetErrorIfFailure - Causes Mat to generate an error, for example a zero pivot, is detected.
96 
97    Logically Collective on Mat
98 
99    Input Parameters:
100 +  mat -  matrix obtained from MatCreate()
101 -  flg - PETSC_TRUE indicates you want the error generated
102 
103    Level: advanced
104 
105 .seealso: PCSetErrorIfFailure()
106 @*/
107 PetscErrorCode  MatSetErrorIfFailure(Mat mat,PetscBool flg)
108 {
109   PetscFunctionBegin;
110   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
111   PetscValidLogicalCollectiveBool(mat,flg,2);
112   mat->erroriffailure = flg;
113   PetscFunctionReturn(0);
114 }
115 
116 /*@
117   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
118 
119   Collective on Mat
120 
121   Input Parameters:
122 +  A - the matrix
123 .  m - number of local rows (or PETSC_DECIDE)
124 .  n - number of local columns (or PETSC_DECIDE)
125 .  M - number of global rows (or PETSC_DETERMINE)
126 -  N - number of global columns (or PETSC_DETERMINE)
127 
128    Notes:
129    m (n) and M (N) cannot be both PETSC_DECIDE
130    If one processor calls this with M (N) of PETSC_DECIDE then all processors must, otherwise the program will hang.
131 
132    If PETSC_DECIDE is not used for the arguments 'm' and 'n', then the
133    user must ensure that they are chosen to be compatible with the
134    vectors. To do this, one first considers the matrix-vector product
135    'y = A x'. The 'm' that is used in the above routine must match the
136    local size used in the vector creation routine VecCreateMPI() for 'y'.
137    Likewise, the 'n' used must match that used as the local size in
138    VecCreateMPI() for 'x'.
139 
140    You cannot change the sizes once they have been set.
141 
142    The sizes must be set before MatSetUp() or MatXXXSetPreallocation() is called.
143 
144   Level: beginner
145 
146 .seealso: MatGetSize(), PetscSplitOwnership()
147 @*/
148 PetscErrorCode  MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
149 {
150   PetscFunctionBegin;
151   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
152   PetscValidLogicalCollectiveInt(A,M,4);
153   PetscValidLogicalCollectiveInt(A,N,5);
154   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);
155   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);
156   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);
157   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);
158   A->rmap->n = m;
159   A->cmap->n = n;
160   A->rmap->N = M > -1 ? M : A->rmap->N;
161   A->cmap->N = N > -1 ? N : A->cmap->N;
162   PetscFunctionReturn(0);
163 }
164 
165 /*@
166    MatSetFromOptions - Creates a matrix where the type is determined
167    from the options database. Generates a parallel MPI matrix if the
168    communicator has more than one processor.  The default matrix type is
169    AIJ, using the routines MatCreateSeqAIJ() and MatCreateAIJ() if
170    you do not select a type in the options database.
171 
172    Collective on Mat
173 
174    Input Parameter:
175 .  A - the matrix
176 
177    Options Database Keys:
178 +    -mat_type seqaij   - AIJ type, uses MatCreateSeqAIJ()
179 .    -mat_type mpiaij   - AIJ type, uses MatCreateAIJ()
180 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
181 .    -mat_type mpidense - dense type, uses MatCreateDense()
182 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
183 -    -mat_type mpibaij  - block AIJ type, uses MatCreateBAIJ()
184 
185    Even More Options Database Keys:
186    See the manpages for particular formats (e.g., MatCreateSeqAIJ())
187    for additional format-specific options.
188 
189    Level: beginner
190 
191 .seealso: MatCreateSeqAIJ((), MatCreateAIJ(),
192           MatCreateSeqDense(), MatCreateDense(),
193           MatCreateSeqBAIJ(), MatCreateBAIJ(),
194           MatCreateSeqSBAIJ(), MatCreateSBAIJ(),
195           MatConvert()
196 @*/
197 PetscErrorCode  MatSetFromOptions(Mat B)
198 {
199   PetscErrorCode ierr;
200   const char     *deft = MATAIJ;
201   char           type[256];
202   PetscBool      flg,set;
203 
204   PetscFunctionBegin;
205   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
206 
207   ierr = PetscObjectOptionsBegin((PetscObject)B);CHKERRQ(ierr);
208 
209   if (B->rmap->bs < 0) {
210     PetscInt newbs = -1;
211     ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSetBlockSize",newbs,&newbs,&flg);CHKERRQ(ierr);
212     if (flg) {
213       ierr = PetscLayoutSetBlockSize(B->rmap,newbs);CHKERRQ(ierr);
214       ierr = PetscLayoutSetBlockSize(B->cmap,newbs);CHKERRQ(ierr);
215     }
216   }
217 
218   ierr = PetscOptionsFList("-mat_type","Matrix type","MatSetType",MatList,deft,type,256,&flg);CHKERRQ(ierr);
219   if (flg) {
220     ierr = MatSetType(B,type);CHKERRQ(ierr);
221   } else if (!((PetscObject)B)->type_name) {
222     ierr = MatSetType(B,deft);CHKERRQ(ierr);
223   }
224 
225   ierr = PetscOptionsName("-mat_is_symmetric","Checks if mat is symmetric on MatAssemblyEnd()","MatIsSymmetric",&B->checksymmetryonassembly);CHKERRQ(ierr);
226   ierr = PetscOptionsReal("-mat_is_symmetric","Checks if mat is symmetric on MatAssemblyEnd()","MatIsSymmetric",B->checksymmetrytol,&B->checksymmetrytol,NULL);CHKERRQ(ierr);
227   ierr = PetscOptionsBool("-mat_null_space_test","Checks if provided null space is correct in MatAssemblyEnd()","MatSetNullSpaceTest",B->checknullspaceonassembly,&B->checknullspaceonassembly,NULL);CHKERRQ(ierr);
228   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);
229 
230   if (B->ops->setfromoptions) {
231     ierr = (*B->ops->setfromoptions)(PetscOptionsObject,B);CHKERRQ(ierr);
232   }
233 
234   flg  = PETSC_FALSE;
235   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);
236   if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,flg);CHKERRQ(ierr);}
237   flg  = PETSC_FALSE;
238   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);
239   if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,flg);CHKERRQ(ierr);}
240   flg  = PETSC_FALSE;
241   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);
242   if (set) {ierr = MatSetOption(B,MAT_IGNORE_ZERO_ENTRIES,flg);CHKERRQ(ierr);}
243 
244   /* process any options handlers added with PetscObjectAddOptionsHandler() */
245   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)B);CHKERRQ(ierr);
246   ierr = PetscOptionsEnd();CHKERRQ(ierr);
247   PetscFunctionReturn(0);
248 }
249 
250 /*@C
251    MatXAIJSetPreallocation - set preallocation for serial and parallel AIJ, BAIJ, and SBAIJ matrices and their unassembled versions.
252 
253    Collective on Mat
254 
255    Input Arguments:
256 +  A - matrix being preallocated
257 .  bs - block size
258 .  dnnz - number of nonzero column blocks per block row of diagonal part of parallel matrix
259 .  onnz - number of nonzero column blocks per block row of off-diagonal part of parallel matrix
260 .  dnnzu - number of nonzero column blocks per block row of upper-triangular part of diagonal part of parallel matrix
261 -  onnzu - number of nonzero column blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
262 
263    Level: beginner
264 
265 .seealso: MatSeqAIJSetPreallocation(), MatMPIAIJSetPreallocation(), MatSeqBAIJSetPreallocation(), MatMPIBAIJSetPreallocation(), MatSeqSBAIJSetPreallocation(), MatMPISBAIJSetPreallocation(),
266           PetscSplitOwnership()
267 @*/
268 PetscErrorCode MatXAIJSetPreallocation(Mat A,PetscInt bs,const PetscInt dnnz[],const PetscInt onnz[],const PetscInt dnnzu[],const PetscInt onnzu[])
269 {
270   PetscErrorCode ierr;
271   PetscInt       cbs;
272   void           (*aij)(void);
273   void           (*is)(void);
274   void           (*hyp)(void) = NULL;
275 
276   PetscFunctionBegin;
277   if (bs != PETSC_DECIDE) { /* don't mess with an already set block size */
278     ierr = MatSetBlockSize(A,bs);CHKERRQ(ierr);
279   }
280   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
281   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
282   ierr = MatGetBlockSizes(A,&bs,&cbs);CHKERRQ(ierr);
283   /* these routines assumes bs == cbs, this should be checked somehow */
284   ierr = MatSeqBAIJSetPreallocation(A,bs,0,dnnz);CHKERRQ(ierr);
285   ierr = MatMPIBAIJSetPreallocation(A,bs,0,dnnz,0,onnz);CHKERRQ(ierr);
286   ierr = MatSeqSBAIJSetPreallocation(A,bs,0,dnnzu);CHKERRQ(ierr);
287   ierr = MatMPISBAIJSetPreallocation(A,bs,0,dnnzu,0,onnzu);CHKERRQ(ierr);
288   /*
289     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
290     good before going on with it.
291   */
292   ierr = PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
293   ierr = PetscObjectQueryFunction((PetscObject)A,"MatISSetPreallocation_C",&is);CHKERRQ(ierr);
294 #if defined(PETSC_HAVE_HYPRE)
295   ierr = PetscObjectQueryFunction((PetscObject)A,"MatHYPRESetPreallocation_C",&hyp);CHKERRQ(ierr);
296 #endif
297   if (!aij && !is && !hyp) {
298     ierr = PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
299   }
300   if (aij || is || hyp) {
301     if (bs == cbs && bs == 1) {
302       ierr = MatSeqAIJSetPreallocation(A,0,dnnz);CHKERRQ(ierr);
303       ierr = MatMPIAIJSetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
304       ierr = MatISSetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
305 #if defined(PETSC_HAVE_HYPRE)
306       ierr = MatHYPRESetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
307 #endif
308     } else { /* Convert block-row precallocation to scalar-row */
309       PetscInt i,m,*sdnnz,*sonnz;
310       ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr);
311       ierr = PetscMalloc2((!!dnnz)*m,&sdnnz,(!!onnz)*m,&sonnz);CHKERRQ(ierr);
312       for (i=0; i<m; i++) {
313         if (dnnz) sdnnz[i] = dnnz[i/bs] * cbs;
314         if (onnz) sonnz[i] = onnz[i/bs] * cbs;
315       }
316       ierr = MatSeqAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL);CHKERRQ(ierr);
317       ierr = MatMPIAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
318       ierr = MatISSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
319 #if defined(PETSC_HAVE_HYPRE)
320       ierr = MatHYPRESetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
321 #endif
322       ierr = PetscFree2(sdnnz,sonnz);CHKERRQ(ierr);
323     }
324   }
325   PetscFunctionReturn(0);
326 }
327 
328 /*
329         Merges some information from Cs header to A; the C object is then destroyed
330 
331         This is somewhat different from MatHeaderReplace() it would be nice to merge the code
332 */
333 PetscErrorCode MatHeaderMerge(Mat A,Mat *C)
334 {
335   PetscErrorCode ierr;
336   PetscInt       refct;
337   PetscOps       Abops;
338   struct _MatOps Aops;
339   char           *mtype,*mname,*mprefix;
340   Mat_Product    *product;
341 
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
344   PetscValidHeaderSpecific(*C,MAT_CLASSID,2);
345   if (A == *C) PetscFunctionReturn(0);
346   PetscCheckSameComm(A,1,*C,2);
347   /* save the parts of A we need */
348   Abops = ((PetscObject)A)->bops[0];
349   Aops  = A->ops[0];
350   refct = ((PetscObject)A)->refct;
351   mtype = ((PetscObject)A)->type_name;
352   mname = ((PetscObject)A)->name;
353   mprefix = ((PetscObject)A)->prefix;
354   product = A->product;
355 
356   /* zero these so the destroy below does not free them */
357   ((PetscObject)A)->type_name = NULL;
358   ((PetscObject)A)->name      = NULL;
359 
360   /* free all the interior data structures from mat */
361   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
362 
363   ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
364   ierr = PetscLayoutDestroy(&A->rmap);CHKERRQ(ierr);
365   ierr = PetscLayoutDestroy(&A->cmap);CHKERRQ(ierr);
366   ierr = PetscFunctionListDestroy(&((PetscObject)A)->qlist);CHKERRQ(ierr);
367   ierr = PetscObjectListDestroy(&((PetscObject)A)->olist);CHKERRQ(ierr);
368 
369   /* copy C over to A */
370   ierr = PetscMemcpy(A,*C,sizeof(struct _p_Mat));CHKERRQ(ierr);
371 
372   /* return the parts of A we saved */
373   ((PetscObject)A)->bops[0]   = Abops;
374   A->ops[0]                   = Aops;
375   ((PetscObject)A)->refct     = refct;
376   ((PetscObject)A)->type_name = mtype;
377   ((PetscObject)A)->name      = mname;
378   ((PetscObject)A)->prefix    = mprefix;
379   A->product                  = product;
380 
381   /* since these two are copied into A we do not want them destroyed in C */
382   ((PetscObject)*C)->qlist = NULL;
383   ((PetscObject)*C)->olist = NULL;
384 
385   ierr = PetscHeaderDestroy(C);CHKERRQ(ierr);
386   PetscFunctionReturn(0);
387 }
388 /*
389         Replace A's header with that of C; the C object is then destroyed
390 
391         This is essentially code moved from MatDestroy()
392 
393         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
394 
395         Used in DM hence is declared PETSC_EXTERN
396 */
397 PETSC_EXTERN PetscErrorCode MatHeaderReplace(Mat A,Mat *C)
398 {
399   PetscErrorCode   ierr;
400   PetscInt         refct;
401   PetscObjectState state;
402   struct _p_Mat    buffer;
403   MatStencilInfo   stencil;
404 
405   PetscFunctionBegin;
406   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
407   PetscValidHeaderSpecific(*C,MAT_CLASSID,2);
408   if (A == *C) PetscFunctionReturn(0);
409   PetscCheckSameComm(A,1,*C,2);
410   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);
411 
412   /* swap C and A */
413   refct   = ((PetscObject)A)->refct;
414   state   = ((PetscObject)A)->state;
415   stencil = A->stencil;
416   ierr  = PetscMemcpy(&buffer,A,sizeof(struct _p_Mat));CHKERRQ(ierr);
417   ierr  = PetscMemcpy(A,*C,sizeof(struct _p_Mat));CHKERRQ(ierr);
418   ierr  = PetscMemcpy(*C,&buffer,sizeof(struct _p_Mat));CHKERRQ(ierr);
419   ((PetscObject)A)->refct   = refct;
420   ((PetscObject)A)->state   = state + 1;
421   A->stencil                = stencil;
422 
423   ((PetscObject)*C)->refct = 1;
424   ierr = MatShellSetOperation(*C,MATOP_DESTROY,(void(*)(void))NULL);CHKERRQ(ierr);
425   ierr = MatDestroy(C);CHKERRQ(ierr);
426   PetscFunctionReturn(0);
427 }
428 
429 /*@
430      MatBindToCPU - marks a matrix to temporarily stay on the CPU and perform computations on the CPU
431 
432    Input Parameters:
433 +   A - the matrix
434 -   flg - bind to the CPU if value of PETSC_TRUE
435 
436    Level: intermediate
437 @*/
438 PetscErrorCode MatBindToCPU(Mat A,PetscBool flg)
439 {
440 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
441   PetscErrorCode ierr;
442 
443   PetscFunctionBegin;
444   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
445   PetscValidLogicalCollectiveBool(A,flg,2);
446   if (A->boundtocpu == flg) PetscFunctionReturn(0);
447   A->boundtocpu = flg;
448   if (A->ops->bindtocpu) {
449     ierr = (*A->ops->bindtocpu)(A,flg);CHKERRQ(ierr);
450   }
451   PetscFunctionReturn(0);
452 #else
453   PetscFunctionBegin;
454   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
455   PetscValidLogicalCollectiveBool(A,flg,2);
456   PetscFunctionReturn(0);
457 #endif
458 }
459 
460 PetscErrorCode MatSetValuesCOO_Basic(Mat A,const PetscScalar coo_v[],InsertMode imode)
461 {
462   IS             is_coo_i,is_coo_j;
463   const PetscInt *coo_i,*coo_j;
464   PetscInt       n,n_i,n_j;
465   PetscScalar    zero = 0.;
466   PetscErrorCode ierr;
467 
468   PetscFunctionBegin;
469   ierr = PetscObjectQuery((PetscObject)A,"__PETSc_coo_i",(PetscObject*)&is_coo_i);CHKERRQ(ierr);
470   ierr = PetscObjectQuery((PetscObject)A,"__PETSc_coo_j",(PetscObject*)&is_coo_j);CHKERRQ(ierr);
471   if (!is_coo_i) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_i IS");
472   if (!is_coo_j) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_COR,"Missing coo_j IS");
473   ierr = ISGetLocalSize(is_coo_i,&n_i);CHKERRQ(ierr);
474   ierr = ISGetLocalSize(is_coo_j,&n_j);CHKERRQ(ierr);
475   if (n_i != n_j)  SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_COR,"Wrong local size %D != %D",n_i,n_j);
476   ierr = ISGetIndices(is_coo_i,&coo_i);CHKERRQ(ierr);
477   ierr = ISGetIndices(is_coo_j,&coo_j);CHKERRQ(ierr);
478   for (n = 0; n < n_i; n++) {
479     ierr = MatSetValue(A,coo_i[n],coo_j[n],coo_v ? coo_v[n] : zero,imode);CHKERRQ(ierr);
480   }
481   ierr = ISRestoreIndices(is_coo_i,&coo_i);CHKERRQ(ierr);
482   ierr = ISRestoreIndices(is_coo_j,&coo_j);CHKERRQ(ierr);
483   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
484   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
485   PetscFunctionReturn(0);
486 }
487 
488 PetscErrorCode MatSetPreallocationCOO_Basic(Mat A,PetscInt ncoo,const PetscInt coo_i[],const PetscInt coo_j[])
489 {
490   Mat            preallocator;
491   IS             is_coo_i,is_coo_j;
492   PetscScalar    zero = 0.0;
493   PetscInt       n;
494   PetscErrorCode ierr;
495 
496   PetscFunctionBegin;
497   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
498   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
499   ierr = MatCreate(PetscObjectComm((PetscObject)A),&preallocator);CHKERRQ(ierr);
500   ierr = MatSetType(preallocator,MATPREALLOCATOR);CHKERRQ(ierr);
501   ierr = MatSetSizes(preallocator,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
502   ierr = MatSetLayouts(preallocator,A->rmap,A->cmap);CHKERRQ(ierr);
503   ierr = MatSetUp(preallocator);CHKERRQ(ierr);
504   for (n = 0; n < ncoo; n++) {
505     ierr = MatSetValue(preallocator,coo_i[n],coo_j[n],zero,INSERT_VALUES);CHKERRQ(ierr);
506   }
507   ierr = MatAssemblyBegin(preallocator,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
508   ierr = MatAssemblyEnd(preallocator,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
509   ierr = MatPreallocatorPreallocate(preallocator,PETSC_TRUE,A);CHKERRQ(ierr);
510   ierr = MatDestroy(&preallocator);CHKERRQ(ierr);
511   ierr = ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_i,PETSC_COPY_VALUES,&is_coo_i);CHKERRQ(ierr);
512   ierr = ISCreateGeneral(PETSC_COMM_SELF,ncoo,coo_j,PETSC_COPY_VALUES,&is_coo_j);CHKERRQ(ierr);
513   ierr = PetscObjectCompose((PetscObject)A,"__PETSc_coo_i",(PetscObject)is_coo_i);CHKERRQ(ierr);
514   ierr = PetscObjectCompose((PetscObject)A,"__PETSc_coo_j",(PetscObject)is_coo_j);CHKERRQ(ierr);
515   ierr = ISDestroy(&is_coo_i);CHKERRQ(ierr);
516   ierr = ISDestroy(&is_coo_j);CHKERRQ(ierr);
517   PetscFunctionReturn(0);
518 }
519 
520 /*@C
521    MatSetPreallocationCOO - set preallocation for matrices using a coordinate format of the entries
522 
523    Collective on Mat
524 
525    Input Arguments:
526 +  A - matrix being preallocated
527 .  ncoo - number of entries in the locally owned part of the parallel matrix
528 .  coo_i - row indices
529 -  coo_j - column indices
530 
531    Level: beginner
532 
533    Notes: Entries can be repeated. Currently optimized for cuSPARSE matrices only.
534 
535 .seealso: MatSetValuesCOO(), MatSeqAIJSetPreallocation(), MatMPIAIJSetPreallocation(), MatSeqBAIJSetPreallocation(), MatMPIBAIJSetPreallocation(), MatSeqSBAIJSetPreallocation(), MatMPISBAIJSetPreallocation()
536 @*/
537 PetscErrorCode MatSetPreallocationCOO(Mat A,PetscInt ncoo,const PetscInt coo_i[],const PetscInt coo_j[])
538 {
539   PetscErrorCode (*f)(Mat,PetscInt,const PetscInt[],const PetscInt[]) = NULL;
540   PetscErrorCode ierr;
541 
542   PetscFunctionBegin;
543   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
544   PetscValidType(A,1);
545   if (ncoo) PetscValidIntPointer(coo_i,3);
546   if (ncoo) PetscValidIntPointer(coo_j,4);
547   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
548   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
549   if (PetscDefined(USE_DEBUG)) {
550     PetscInt i;
551     for (i = 0; i < ncoo; i++) {
552       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);
553       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);
554     }
555   }
556   ierr = PetscObjectQueryFunction((PetscObject)A,"MatSetPreallocationCOO_C",&f);CHKERRQ(ierr);
557   if (f) {
558     ierr = (*f)(A,ncoo,coo_i,coo_j);CHKERRQ(ierr);
559   } else { /* allow fallback, very slow */
560     ierr = MatSetPreallocationCOO_Basic(A,ncoo,coo_i,coo_j);CHKERRQ(ierr);
561   }
562   PetscFunctionReturn(0);
563 }
564 
565 /*@C
566    MatSetValuesCOO - set values at once in a matrix preallocated using MatSetPreallocationCOO
567 
568    Collective on Mat
569 
570    Input Arguments:
571 +  A - matrix being preallocated
572 .  coo_v - the matrix values
573 -  imode - the insert mode
574 
575    Level: beginner
576 
577    Notes: The values must follow the order of the indices prescribed with MatSetPreallocationCOO().
578           Currently optimized for cuSPARSE matrices only.
579 
580 .seealso: MatSetPreallocationCOO(), InsertMode, INSERT_VALUES, ADD_VALUES
581 @*/
582 PetscErrorCode MatSetValuesCOO(Mat A, const PetscScalar coo_v[], InsertMode imode)
583 {
584   PetscErrorCode (*f)(Mat,const PetscScalar[],InsertMode) = NULL;
585   PetscErrorCode ierr;
586 
587   PetscFunctionBegin;
588   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
589   PetscValidType(A,1);
590   MatCheckPreallocated(A,1);
591   PetscValidLogicalCollectiveEnum(A,imode,4);
592   ierr = PetscObjectQueryFunction((PetscObject)A,"MatSetValuesCOO_C",&f);CHKERRQ(ierr);
593   if (f) {
594     ierr = (*f)(A,coo_v,imode);CHKERRQ(ierr);
595   } else { /* allow fallback */
596     ierr = MatSetValuesCOO_Basic(A,coo_v,imode);CHKERRQ(ierr);
597   }
598   PetscFunctionReturn(0);
599 }
600