xref: /petsc/src/mat/utils/gcreate.c (revision 247e2d9283ff1bbf8950108a11f1a3a3a92a3dd5)
1 
2 #include <private/matimpl.h>       /*I "petscmat.h"  I*/
3 
4 #if 0
5 #undef __FUNCT__
6 #define __FUNCT__ "MatPublish_Base"
7 static PetscErrorCode MatPublish_Base(PetscObject obj)
8 {
9   PetscFunctionBegin;
10   PetscFunctionReturn(0);
11 }
12 #endif
13 
14 #undef __FUNCT__
15 #define __FUNCT__ "MatCreate"
16 /*@
17    MatCreate - Creates a matrix where the type is determined
18    from either a call to MatSetType() or from the options database
19    with a call to MatSetFromOptions(). The default matrix type is
20    AIJ, using the routines MatCreateSeqAIJ() or MatCreateMPIAIJ()
21    if you do not set a type in the options database. If you never
22    call MatSetType() or MatSetFromOptions() it will generate an
23    error when you try to use the matrix.
24 
25    Collective on MPI_Comm
26 
27    Input Parameter:
28 .  comm - MPI communicator
29 
30    Output Parameter:
31 .  A - the matrix
32 
33    Options Database Keys:
34 +    -mat_type seqaij   - AIJ type, uses MatCreateSeqAIJ()
35 .    -mat_type mpiaij   - AIJ type, uses MatCreateMPIAIJ()
36 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
37 .    -mat_type mpidense - dense type, uses MatCreateMPIDense()
38 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
39 -    -mat_type mpibaij  - block AIJ type, uses MatCreateMPIBAIJ()
40 
41    Even More Options Database Keys:
42    See the manpages for particular formats (e.g., MatCreateSeqAIJ())
43    for additional format-specific options.
44 
45    Notes:
46 
47    Level: beginner
48 
49    User manual sections:
50 +   sec_matcreate
51 -   chapter_matrices
52 
53 .keywords: matrix, create
54 
55 .seealso: MatCreateSeqAIJ(), MatCreateMPIAIJ(),
56           MatCreateSeqDense(), MatCreateMPIDense(),
57           MatCreateSeqBAIJ(), MatCreateMPIBAIJ(),
58           MatCreateSeqSBAIJ(), MatCreateMPISBAIJ(),
59           MatConvert()
60 @*/
61 PetscErrorCode  MatCreate(MPI_Comm comm,Mat *A)
62 {
63   Mat            B;
64   PetscErrorCode ierr;
65 
66   PetscFunctionBegin;
67   PetscValidPointer(A,2);
68 
69   *A = PETSC_NULL;
70 #ifndef PETSC_USE_DYNAMIC_LIBRARIES
71   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
72 #endif
73 
74   ierr = PetscHeaderCreate(B,_p_Mat,struct _MatOps,MAT_CLASSID,0,"Mat","Matrix","Mat",comm,MatDestroy,MatView);CHKERRQ(ierr);
75   ierr = PetscLayoutCreate(comm,&B->rmap);CHKERRQ(ierr);
76   ierr = PetscLayoutCreate(comm,&B->cmap);CHKERRQ(ierr);
77   B->preallocated  = PETSC_FALSE;
78   *A               = B;
79   PetscFunctionReturn(0);
80 }
81 
82 #undef __FUNCT__
83 #define __FUNCT__ "MatSetSizes"
84 /*@
85   MatSetSizes - Sets the local and global sizes, and checks to determine compatibility
86 
87   Collective on Mat
88 
89   Input Parameters:
90 +  A - the matrix
91 .  m - number of local rows (or PETSC_DECIDE)
92 .  n - number of local columns (or PETSC_DECIDE)
93 .  M - number of global rows (or PETSC_DETERMINE)
94 -  N - number of global columns (or PETSC_DETERMINE)
95 
96    Notes:
97    m (n) and M (N) cannot be both PETSC_DECIDE
98    If one processor calls this with M (N) of PETSC_DECIDE then all processors must, otherwise the program will hang.
99 
100    If PETSC_DECIDE is not used for the arguments 'm' and 'n', then the
101    user must ensure that they are chosen to be compatible with the
102    vectors. To do this, one first considers the matrix-vector product
103    'y = A x'. The 'm' that is used in the above routine must match the
104    local size used in the vector creation routine VecCreateMPI() for 'y'.
105    Likewise, the 'n' used must match that used as the local size in
106    VecCreateMPI() for 'x'.
107 
108   Level: beginner
109 
110 .seealso: MatGetSize(), PetscSplitOwnership()
111 @*/
112 PetscErrorCode  MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
113 {
114   PetscErrorCode ierr;
115 
116   PetscFunctionBegin;
117   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
118   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);
119   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);
120   if (A->ops->setsizes) {
121     /* Since this will not be set until the type has been set, this will NOT be called on the initial
122        call of MatSetSizes() (which must be called BEFORE MatSetType() */
123     ierr = (*A->ops->setsizes)(A,m,n,M,N);CHKERRQ(ierr);
124   } else {
125     if ((A->rmap->n >= 0 || A->rmap->N >= 0) && (A->rmap->n != m || 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);
126     if ((A->cmap->n >= 0 || A->cmap->N >= 0) && (A->cmap->n != n || 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);
127   }
128   A->rmap->n = m;
129   A->cmap->n = n;
130   A->rmap->N = M;
131   A->cmap->N = N;
132 
133   PetscFunctionReturn(0);
134 }
135 
136 #undef __FUNCT__
137 #define __FUNCT__ "MatSetFromOptions"
138 /*@
139    MatSetFromOptions - Creates a matrix where the type is determined
140    from the options database. Generates a parallel MPI matrix if the
141    communicator has more than one processor.  The default matrix type is
142    AIJ, using the routines MatCreateSeqAIJ() and MatCreateMPIAIJ() if
143    you do not select a type in the options database.
144 
145    Collective on Mat
146 
147    Input Parameter:
148 .  A - the matrix
149 
150    Options Database Keys:
151 +    -mat_type seqaij   - AIJ type, uses MatCreateSeqAIJ()
152 .    -mat_type mpiaij   - AIJ type, uses MatCreateMPIAIJ()
153 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
154 .    -mat_type mpidense - dense type, uses MatCreateMPIDense()
155 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
156 -    -mat_type mpibaij  - block AIJ type, uses MatCreateMPIBAIJ()
157 
158    Even More Options Database Keys:
159    See the manpages for particular formats (e.g., MatCreateSeqAIJ())
160    for additional format-specific options.
161 
162    Level: beginner
163 
164 .keywords: matrix, create
165 
166 .seealso: MatCreateSeqAIJ((), MatCreateMPIAIJ(),
167           MatCreateSeqDense(), MatCreateMPIDense(),
168           MatCreateSeqBAIJ(), MatCreateMPIBAIJ(),
169           MatCreateSeqSBAIJ(), MatCreateMPISBAIJ(),
170           MatConvert()
171 @*/
172 PetscErrorCode  MatSetFromOptions(Mat B)
173 {
174   PetscErrorCode ierr;
175   const char     *deft = MATAIJ;
176   char           type[256];
177   PetscBool      flg,set;
178 
179   PetscFunctionBegin;
180   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
181 
182   ierr = PetscObjectOptionsBegin((PetscObject)B);CHKERRQ(ierr);
183     ierr = PetscOptionsList("-mat_type","Matrix type","MatSetType",MatList,deft,type,256,&flg);CHKERRQ(ierr);
184     if (flg) {
185       ierr = MatSetType(B,type);CHKERRQ(ierr);
186     } else if (!((PetscObject)B)->type_name) {
187       ierr = MatSetType(B,deft);CHKERRQ(ierr);
188     }
189 
190     if (B->ops->setfromoptions) {
191       ierr = (*B->ops->setfromoptions)(B);CHKERRQ(ierr);
192     }
193 
194     flg = PETSC_FALSE;
195     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);
196     if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,flg);CHKERRQ(ierr);}
197     flg = PETSC_FALSE;
198     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);
199     if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,flg);CHKERRQ(ierr);}
200 
201     /* process any options handlers added with PetscObjectAddOptionsHandler() */
202     ierr = PetscObjectProcessOptionsHandlers((PetscObject)B);CHKERRQ(ierr);
203   ierr = PetscOptionsEnd();CHKERRQ(ierr);
204 
205   PetscFunctionReturn(0);
206 }
207 
208 #undef __FUNCT__
209 #define __FUNCT__ "MatSetUpPreallocation"
210 /*@
211    MatSetUpPreallocation - If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
212 
213    Collective on Mat
214 
215    Input Parameter:
216 .  A - the matrix
217 
218    Level: advanced
219 
220    Notes: See the Performance chapter of the PETSc users manual for how to preallocate matrices
221 
222 .keywords: matrix, create
223 
224 .seealso: MatCreateSeqAIJ((), MatCreateMPIAIJ(),
225           MatCreateSeqDense(), MatCreateMPIDense(),
226           MatCreateSeqBAIJ(), MatCreateMPIBAIJ(),
227           MatCreateSeqSBAIJ(), MatCreateMPISBAIJ(),
228           MatConvert()
229 @*/
230 PetscErrorCode  MatSetUpPreallocation(Mat B)
231 {
232   PetscErrorCode ierr;
233 
234   PetscFunctionBegin;
235   if (!B->preallocated && B->ops->setuppreallocation) {
236     ierr = PetscInfo(B,"Warning not preallocating matrix storage\n");CHKERRQ(ierr);
237     ierr = (*B->ops->setuppreallocation)(B);CHKERRQ(ierr);
238   }
239   B->preallocated = PETSC_TRUE;
240   PetscFunctionReturn(0);
241 }
242 
243 #undef __FUNCT__
244 #define __FUNCT__ "MatXAIJSetPreallocation"
245 /*@
246    MatXAIJSetPreallocation - set preallocation for serial and parallel AIJ, BAIJ, and SBAIJ matrices
247 
248    Collective on Mat
249 
250    Input Arguments:
251 +  A - matrix being preallocated
252 .  bs - block size
253 .  dnz - maximum number of nonzero entries per row of diagonal block of parallel matrix
254 .  dnnz - number of nonzeros per row of diagonal block of parallel matrix
255 .  onz - maximum number of nonzero entries per row of off-diagonal block of parallel matrix
256 .  onnz - number of nonzeros per row of off-diagonal block of parallel matrix
257 .  dnzu - maximum number of nonzero entries per row of upper-triangular part of diagonal block of parallel matrix
258 .  dnnzu - number of nonzeros per row of upper-triangular part of diagonal block of parallel matrix
259 .  onzu - maximum number of nonzero entries per row of upper-triangular part of off-diagonal block of parallel matrix
260 -  onnzu - number of nonzeros per row of upper-triangular part of off-diagonal block of parallel matrix
261 
262    Level: beginner
263 
264 .seealso: MatSeqAIJSetPreallocation(), MatMPIAIJSetPreallocation(), MatSeqBAIJSetPreallocation(), MatMPIBAIJSetPreallocation(), MatSeqSBAIJSetPreallocation(), MatMPISBAIJSetPreallocation()
265 @*/
266 PetscErrorCode MatXAIJSetPreallocation(Mat A,PetscInt bs,PetscInt dnz,const PetscInt *dnnz,PetscInt onz,const PetscInt *onnz,PetscInt dnzu,const PetscInt *dnnzu,PetscInt onzu,const PetscInt *onnzu)
267 {
268   PetscErrorCode ierr;
269   void (*aij)(void);
270 
271   PetscFunctionBegin;
272   ierr = MatSeqBAIJSetPreallocation(A,bs,dnz,dnnz);CHKERRQ(ierr);
273   ierr = MatMPIBAIJSetPreallocation(A,bs,dnz,dnnz,onz,onnz);CHKERRQ(ierr);
274   ierr = MatSeqSBAIJSetPreallocation(A,bs,dnzu,dnnzu);CHKERRQ(ierr);
275   ierr = MatMPISBAIJSetPreallocation(A,bs,dnzu,dnnzu,onzu,onnzu);CHKERRQ(ierr);
276   /*
277     In general, we have to do extra work to preallocate for scalar (AIJ) matrices so we check whether it will do any
278     good before going on with it.
279   */
280   ierr = PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
281   if (!aij) {
282     ierr = PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
283   }
284   if (aij) {
285     if (bs == 1) {
286       ierr = MatSeqAIJSetPreallocation(A,dnz,dnnz);CHKERRQ(ierr);
287       ierr = MatMPIAIJSetPreallocation(A,dnz,dnnz,onz,onnz);CHKERRQ(ierr);
288     } else if (!dnnz) {
289       ierr = MatSeqAIJSetPreallocation(A,dnz*bs,PETSC_NULL);CHKERRQ(ierr);
290       ierr = MatMPIAIJSetPreallocation(A,dnz*bs,PETSC_NULL,onz*bs,PETSC_NULL);CHKERRQ(ierr);
291     } else {                    /* The user has provided preallocation per block-row, convert it to per scalar-row */
292       PetscInt i,m,*sdnnz,*sonnz;
293       ierr = MatGetLocalSize(A,&m,PETSC_NULL);CHKERRQ(ierr);
294       ierr = PetscMalloc2((!!dnnz)*m*bs,PetscInt,&sdnnz,(!!onnz)*m*bs,PetscInt,&sonnz);CHKERRQ(ierr);
295       for (i=0; i<m*bs; i++) {
296         if (dnnz) sdnnz[i] = dnnz[i/bs] * bs;
297         if (onnz) sonnz[i] = onnz[i/bs] * bs;
298       }
299       ierr = MatSeqAIJSetPreallocation(A,dnz*bs,dnnz?sdnnz:PETSC_NULL);CHKERRQ(ierr);
300       ierr = MatMPIAIJSetPreallocation(A,dnz*bs,dnnz?sdnnz:PETSC_NULL,onz*bs,onnz?sonnz:PETSC_NULL);CHKERRQ(ierr);
301       ierr = PetscFree2(sdnnz,sonnz);CHKERRQ(ierr);
302     }
303   }
304   ierr = MatSetBlockSize(A,bs);CHKERRQ(ierr);
305   PetscFunctionReturn(0);
306 }
307 
308 /*
309         Merges some information from Cs header to A; the C object is then destroyed
310 
311         This is somewhat different from MatHeaderReplace() it would be nice to merge the code
312 */
313 #undef __FUNCT__
314 #define __FUNCT__ "MatHeaderMerge"
315 PetscErrorCode MatHeaderMerge(Mat A,Mat C)
316 {
317   PetscErrorCode         ierr;
318   PetscInt               refct;
319   PetscOps               *Abops;
320   MatOps                 Aops;
321   char                   *mtype,*mname;
322   void                   *spptr;
323 
324   PetscFunctionBegin;
325   /* save the parts of A we need */
326   Abops = ((PetscObject)A)->bops;
327   Aops  = A->ops;
328   refct = ((PetscObject)A)->refct;
329   mtype = ((PetscObject)A)->type_name;
330   mname = ((PetscObject)A)->name;
331   spptr = A->spptr;
332 
333   /* zero these so the destroy below does not free them */
334   ((PetscObject)A)->type_name = 0;
335   ((PetscObject)A)->name      = 0;
336 
337   /* free all the interior data structures from mat */
338   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
339 
340   ierr = PetscFree(C->spptr);CHKERRQ(ierr);
341 
342   ierr = PetscLayoutDestroy(&A->rmap);CHKERRQ(ierr);
343   ierr = PetscLayoutDestroy(&A->cmap);CHKERRQ(ierr);
344   ierr = PetscFListDestroy(&((PetscObject)A)->qlist);CHKERRQ(ierr);
345   ierr = PetscOListDestroy(&((PetscObject)A)->olist);CHKERRQ(ierr);
346 
347   /* copy C over to A */
348   ierr  = PetscMemcpy(A,C,sizeof(struct _p_Mat));CHKERRQ(ierr);
349 
350   /* return the parts of A we saved */
351   ((PetscObject)A)->bops      = Abops;
352   A->ops                      = Aops;
353   ((PetscObject)A)->refct     = refct;
354   ((PetscObject)A)->type_name = mtype;
355   ((PetscObject)A)->name      = mname;
356   A->spptr                    = spptr;
357 
358   /* since these two are copied into A we do not want them destroyed in C */
359   ((PetscObject)C)->qlist = 0;
360   ((PetscObject)C)->olist = 0;
361   ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
362   PetscFunctionReturn(0);
363 }
364 /*
365         Replace A's header with that of C; the C object is then destroyed
366 
367         This is essentially code moved from MatDestroy()
368 
369         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
370 */
371 #undef __FUNCT__
372 #define __FUNCT__ "MatHeaderReplace"
373 PetscErrorCode MatHeaderReplace(Mat A,Mat C)
374 {
375   PetscErrorCode ierr;
376   PetscInt refct;
377 
378   PetscFunctionBegin;
379   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
380   PetscValidHeaderSpecific(C,MAT_CLASSID,2);
381   if (A == C) PetscFunctionReturn(0);
382   PetscCheckSameComm(A,1,C,2);
383   if (((PetscObject)C)->refct != 1) SETERRQ1(((PetscObject)C)->comm,PETSC_ERR_ARG_WRONGSTATE,"Object C has refct %D > 1, would leave hanging reference",((PetscObject)C)->refct);
384 
385   /* free all the interior data structures from mat */
386   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
387   ierr = PetscHeaderDestroy_Private((PetscObject)A);CHKERRQ(ierr);
388   ierr = PetscFree(A->ops);CHKERRQ(ierr);
389   ierr = PetscLayoutDestroy(&A->rmap);CHKERRQ(ierr);
390   ierr = PetscLayoutDestroy(&A->cmap);CHKERRQ(ierr);
391   ierr = PetscFree(A->spptr);CHKERRQ(ierr);
392 
393   /* copy C over to A */
394   refct = ((PetscObject)A)->refct;
395   ierr = PetscMemcpy(A,C,sizeof(struct _p_Mat));CHKERRQ(ierr);
396   ((PetscObject)A)->refct = refct;
397   ierr = PetscLogObjectDestroy((PetscObject)C);CHKERRQ(ierr);
398   ierr = PetscFree(C);CHKERRQ(ierr);
399   PetscFunctionReturn(0);
400 }
401