xref: /petsc/src/mat/utils/gcreate.c (revision 95cbbfd359aa2cc7e96afc77b64e4c0540dc7b23)
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     ierr = MatSetValues(Y,1,&i,1,&i,&alpha,ADD_VALUES);CHKERRQ(ierr);
26   }
27   ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28   ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29   ierr = MatSetOption(Y,MAT_NO_OFF_PROC_ENTRIES,prevoption);CHKERRQ(ierr);
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 on MPI_Comm
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    Notes:
63 
64    Level: beginner
65 
66    User manual sections:
67 +   sec_matcreate
68 -   chapter_matrices
69 
70 .keywords: matrix, create
71 
72 .seealso: MatCreateSeqAIJ(), MatCreateAIJ(),
73           MatCreateSeqDense(), MatCreateDense(),
74           MatCreateSeqBAIJ(), MatCreateBAIJ(),
75           MatCreateSeqSBAIJ(), MatCreateSBAIJ(),
76           MatConvert()
77 @*/
78 PetscErrorCode  MatCreate(MPI_Comm comm,Mat *A)
79 {
80   Mat            B;
81   PetscErrorCode ierr;
82 
83   PetscFunctionBegin;
84   PetscValidPointer(A,2);
85 
86   *A = NULL;
87   ierr = MatInitializePackage();CHKERRQ(ierr);
88 
89   ierr = PetscHeaderCreate(B,MAT_CLASSID,"Mat","Matrix","Mat",comm,MatDestroy,MatView);CHKERRQ(ierr);
90   ierr = PetscLayoutCreate(comm,&B->rmap);CHKERRQ(ierr);
91   ierr = PetscLayoutCreate(comm,&B->cmap);CHKERRQ(ierr);
92   ierr = PetscStrallocpy(VECSTANDARD,&B->defaultvectype);CHKERRQ(ierr);
93 
94   B->congruentlayouts = PETSC_DECIDE;
95   B->preallocated     = PETSC_FALSE;
96   *A                  = B;
97   PetscFunctionReturn(0);
98 }
99 
100 /*@
101    MatSetErrorIfFailure - Causes Mat to generate an error, for example a zero pivot, is detected.
102 
103    Logically Collective on Mat
104 
105    Input Parameters:
106 +  mat -  matrix obtained from MatCreate()
107 -  flg - PETSC_TRUE indicates you want the error generated
108 
109    Level: advanced
110 
111 .keywords: Mat, set, initial guess, nonzero
112 
113 .seealso: PCSetErrorIfFailure()
114 @*/
115 PetscErrorCode  MatSetErrorIfFailure(Mat mat,PetscBool flg)
116 {
117   PetscFunctionBegin;
118   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
119   PetscValidLogicalCollectiveBool(mat,flg,2);
120   mat->erroriffailure = flg;
121   PetscFunctionReturn(0);
122 }
123 
124 /*@
125   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
126 
127   Collective on Mat
128 
129   Input Parameters:
130 +  A - the matrix
131 .  m - number of local rows (or PETSC_DECIDE)
132 .  n - number of local columns (or PETSC_DECIDE)
133 .  M - number of global rows (or PETSC_DETERMINE)
134 -  N - number of global columns (or PETSC_DETERMINE)
135 
136    Notes:
137    m (n) and M (N) cannot be both PETSC_DECIDE
138    If one processor calls this with M (N) of PETSC_DECIDE then all processors must, otherwise the program will hang.
139 
140    If PETSC_DECIDE is not used for the arguments 'm' and 'n', then the
141    user must ensure that they are chosen to be compatible with the
142    vectors. To do this, one first considers the matrix-vector product
143    'y = A x'. The 'm' that is used in the above routine must match the
144    local size used in the vector creation routine VecCreateMPI() for 'y'.
145    Likewise, the 'n' used must match that used as the local size in
146    VecCreateMPI() for 'x'.
147 
148    You cannot change the sizes once they have been set.
149 
150    The sizes must be set before MatSetUp() or MatXXXSetPreallocation() is called.
151 
152   Level: beginner
153 
154 .seealso: MatGetSize(), PetscSplitOwnership()
155 @*/
156 PetscErrorCode  MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
157 {
158   PetscFunctionBegin;
159   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
160   if (M > 0) PetscValidLogicalCollectiveInt(A,M,4);
161   if (N > 0) PetscValidLogicalCollectiveInt(A,N,5);
162   if (M > 0 && m > M) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local column size %D cannot be larger than global column size %D",m,M);
163   if (N > 0 && n > N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local row size %D cannot be larger than global row size %D",n,N);
164   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);
165   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);
166   A->rmap->n = m;
167   A->cmap->n = n;
168   A->rmap->N = M > -1 ? M : A->rmap->N;
169   A->cmap->N = N > -1 ? N : A->cmap->N;
170   PetscFunctionReturn(0);
171 }
172 
173 /*@
174    MatSetFromOptions - Creates a matrix where the type is determined
175    from the options database. Generates a parallel MPI matrix if the
176    communicator has more than one processor.  The default matrix type is
177    AIJ, using the routines MatCreateSeqAIJ() and MatCreateAIJ() if
178    you do not select a type in the options database.
179 
180    Collective on Mat
181 
182    Input Parameter:
183 .  A - the matrix
184 
185    Options Database Keys:
186 +    -mat_type seqaij   - AIJ type, uses MatCreateSeqAIJ()
187 .    -mat_type mpiaij   - AIJ type, uses MatCreateAIJ()
188 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
189 .    -mat_type mpidense - dense type, uses MatCreateDense()
190 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
191 -    -mat_type mpibaij  - block AIJ type, uses MatCreateBAIJ()
192 
193    Even More Options Database Keys:
194    See the manpages for particular formats (e.g., MatCreateSeqAIJ())
195    for additional format-specific options.
196 
197    Level: beginner
198 
199 .keywords: matrix, create
200 
201 .seealso: MatCreateSeqAIJ((), MatCreateAIJ(),
202           MatCreateSeqDense(), MatCreateDense(),
203           MatCreateSeqBAIJ(), MatCreateBAIJ(),
204           MatCreateSeqSBAIJ(), MatCreateSBAIJ(),
205           MatConvert()
206 @*/
207 PetscErrorCode  MatSetFromOptions(Mat B)
208 {
209   PetscErrorCode ierr;
210   const char     *deft = MATAIJ;
211   char           type[256];
212   PetscBool      flg,set;
213 
214   PetscFunctionBegin;
215   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
216 
217   ierr = PetscObjectOptionsBegin((PetscObject)B);CHKERRQ(ierr);
218 
219   if (B->rmap->bs < 0) {
220     PetscInt newbs = -1;
221     ierr = PetscOptionsInt("-mat_block_size","Set the blocksize used to store the matrix","MatSetBlockSize",newbs,&newbs,&flg);CHKERRQ(ierr);
222     if (flg) {
223       ierr = PetscLayoutSetBlockSize(B->rmap,newbs);CHKERRQ(ierr);
224       ierr = PetscLayoutSetBlockSize(B->cmap,newbs);CHKERRQ(ierr);
225     }
226   }
227 
228   ierr = PetscOptionsFList("-mat_type","Matrix type","MatSetType",MatList,deft,type,256,&flg);CHKERRQ(ierr);
229   if (flg) {
230     ierr = MatSetType(B,type);CHKERRQ(ierr);
231   } else if (!((PetscObject)B)->type_name) {
232     ierr = MatSetType(B,deft);CHKERRQ(ierr);
233   }
234 
235   ierr = PetscOptionsName("-mat_is_symmetric","Checks if mat is symmetric on MatAssemblyEnd()","MatIsSymmetric",&B->checksymmetryonassembly);CHKERRQ(ierr);
236   ierr = PetscOptionsReal("-mat_is_symmetric","Checks if mat is symmetric on MatAssemblyEnd()","MatIsSymmetric",B->checksymmetrytol,&B->checksymmetrytol,NULL);CHKERRQ(ierr);
237   ierr = PetscOptionsBool("-mat_null_space_test","Checks if provided null space is correct in MatAssemblyEnd()","MatSetNullSpaceTest",B->checknullspaceonassembly,&B->checknullspaceonassembly,NULL);CHKERRQ(ierr);
238   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);
239 
240   if (B->ops->setfromoptions) {
241     ierr = (*B->ops->setfromoptions)(PetscOptionsObject,B);CHKERRQ(ierr);
242   }
243 
244   flg  = PETSC_FALSE;
245   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);
246   if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,flg);CHKERRQ(ierr);}
247   flg  = PETSC_FALSE;
248   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);
249   if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,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 Arguments:
263 +  A - matrix being preallocated
264 .  bs - block size
265 .  dnnz - number of nonzero blocks per block row of diagonal part of parallel matrix
266 .  onnz - number of nonzero blocks per block row of off-diagonal part of parallel matrix
267 .  dnnzu - number of nonzero blocks per block row of upper-triangular part of diagonal part of parallel matrix
268 -  onnzu - number of nonzero 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   void           (*aij)(void);
279   void           (*is)(void);
280   void           (*hyp)(void) = NULL;
281 
282   PetscFunctionBegin;
283   ierr = MatSetBlockSize(A,bs);CHKERRQ(ierr);
284   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
285   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
286   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
287   ierr = MatSeqBAIJSetPreallocation(A,bs,0,dnnz);CHKERRQ(ierr);
288   ierr = MatMPIBAIJSetPreallocation(A,bs,0,dnnz,0,onnz);CHKERRQ(ierr);
289   ierr = MatSeqSBAIJSetPreallocation(A,bs,0,dnnzu);CHKERRQ(ierr);
290   ierr = MatMPISBAIJSetPreallocation(A,bs,0,dnnzu,0,onnzu);CHKERRQ(ierr);
291   /*
292     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
293     good before going on with it.
294   */
295   ierr = PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
296   ierr = PetscObjectQueryFunction((PetscObject)A,"MatISSetPreallocation_C",&is);CHKERRQ(ierr);
297 #if defined(PETSC_HAVE_HYPRE)
298   ierr = PetscObjectQueryFunction((PetscObject)A,"MatHYPRESetPreallocation_C",&hyp);CHKERRQ(ierr);
299 #endif
300   if (!aij && !is && !hyp) {
301     ierr = PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
302   }
303   if (aij || is || hyp) {
304     if (bs == 1) {
305       ierr = MatSeqAIJSetPreallocation(A,0,dnnz);CHKERRQ(ierr);
306       ierr = MatMPIAIJSetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
307       ierr = MatISSetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
308 #if defined(PETSC_HAVE_HYPRE)
309       ierr = MatHYPRESetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
310 #endif
311     } else {                    /* Convert block-row precallocation to scalar-row */
312       PetscInt i,m,*sdnnz,*sonnz;
313       ierr = MatGetLocalSize(A,&m,NULL);CHKERRQ(ierr);
314       ierr = PetscMalloc2((!!dnnz)*m,&sdnnz,(!!onnz)*m,&sonnz);CHKERRQ(ierr);
315       for (i=0; i<m; i++) {
316         if (dnnz) sdnnz[i] = dnnz[i/bs] * bs;
317         if (onnz) sonnz[i] = onnz[i/bs] * bs;
318       }
319       ierr = MatSeqAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL);CHKERRQ(ierr);
320       ierr = MatMPIAIJSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
321       ierr = MatISSetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
322 #if defined(PETSC_HAVE_HYPRE)
323       ierr = MatHYPRESetPreallocation(A,0,dnnz ? sdnnz : NULL,0,onnz ? sonnz : NULL);CHKERRQ(ierr);
324 #endif
325       ierr = PetscFree2(sdnnz,sonnz);CHKERRQ(ierr);
326     }
327   }
328   PetscFunctionReturn(0);
329 }
330 
331 /*
332         Merges some information from Cs header to A; the C object is then destroyed
333 
334         This is somewhat different from MatHeaderReplace() it would be nice to merge the code
335 */
336 PetscErrorCode MatHeaderMerge(Mat A,Mat *C)
337 {
338   PetscErrorCode ierr;
339   PetscInt       refct;
340   PetscOps       Abops;
341   struct _MatOps Aops;
342   char           *mtype,*mname;
343 
344   PetscFunctionBegin;
345   /* save the parts of A we need */
346   Abops = ((PetscObject)A)->bops[0];
347   Aops  = A->ops[0];
348   refct = ((PetscObject)A)->refct;
349   mtype = ((PetscObject)A)->type_name;
350   mname = ((PetscObject)A)->name;
351 
352   /* zero these so the destroy below does not free them */
353   ((PetscObject)A)->type_name = 0;
354   ((PetscObject)A)->name      = 0;
355 
356   /* free all the interior data structures from mat */
357   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
358 
359   ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
360   ierr = PetscLayoutDestroy(&A->rmap);CHKERRQ(ierr);
361   ierr = PetscLayoutDestroy(&A->cmap);CHKERRQ(ierr);
362   ierr = PetscFunctionListDestroy(&((PetscObject)A)->qlist);CHKERRQ(ierr);
363   ierr = PetscObjectListDestroy(&((PetscObject)A)->olist);CHKERRQ(ierr);
364 
365   /* copy C over to A */
366   ierr = PetscMemcpy(A,*C,sizeof(struct _p_Mat));CHKERRQ(ierr);
367 
368   /* return the parts of A we saved */
369   ((PetscObject)A)->bops[0]   = Abops;
370   A->ops[0]                   = Aops;
371   ((PetscObject)A)->refct     = refct;
372   ((PetscObject)A)->type_name = mtype;
373   ((PetscObject)A)->name      = mname;
374 
375   /* since these two are copied into A we do not want them destroyed in C */
376   ((PetscObject)*C)->qlist = 0;
377   ((PetscObject)*C)->olist = 0;
378 
379   ierr = PetscHeaderDestroy(C);CHKERRQ(ierr);
380   PetscFunctionReturn(0);
381 }
382 /*
383         Replace A's header with that of C; the C object is then destroyed
384 
385         This is essentially code moved from MatDestroy()
386 
387         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
388 
389         Used in DM hence is declared PETSC_EXTERN
390 */
391 PETSC_EXTERN PetscErrorCode MatHeaderReplace(Mat A,Mat *C)
392 {
393   PetscErrorCode   ierr;
394   PetscInt         refct;
395   PetscObjectState state;
396   struct _p_Mat    buffer;
397 
398   PetscFunctionBegin;
399   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
400   PetscValidHeaderSpecific(*C,MAT_CLASSID,2);
401   if (A == *C) PetscFunctionReturn(0);
402   PetscCheckSameComm(A,1,*C,2);
403   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);
404 
405   /* swap C and A */
406   refct = ((PetscObject)A)->refct;
407   state = ((PetscObject)A)->state;
408   ierr  = PetscMemcpy(&buffer,A,sizeof(struct _p_Mat));CHKERRQ(ierr);
409   ierr  = PetscMemcpy(A,*C,sizeof(struct _p_Mat));CHKERRQ(ierr);
410   ierr  = PetscMemcpy(*C,&buffer,sizeof(struct _p_Mat));CHKERRQ(ierr);
411   ((PetscObject)A)->refct = refct;
412   ((PetscObject)A)->state = state + 1;
413 
414   ((PetscObject)*C)->refct = 1;
415   ierr = MatDestroy(C);CHKERRQ(ierr);
416   PetscFunctionReturn(0);
417 }
418