xref: /petsc/src/mat/utils/gcreate.c (revision f73d5cc4fab9985badaa1a29b152f456bf59ad34)
1 
2 #include <petsc-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 MatCreateAIJ()
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 MatCreateAIJ()
36 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
37 .    -mat_type mpidense - dense type, uses MatCreateDense()
38 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
39 -    -mat_type mpibaij  - block AIJ type, uses MatCreateBAIJ()
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(), MatCreateAIJ(),
56           MatCreateSeqDense(), MatCreateDense(),
57           MatCreateSeqBAIJ(), MatCreateBAIJ(),
58           MatCreateSeqSBAIJ(), MatCreateSBAIJ(),
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    You cannot change the sizes once they have been set.
109 
110    The sizes must be set before MatSetUp() or MatXXXSetPreallocation() is called.
111 
112   Level: beginner
113 
114 .seealso: MatGetSize(), PetscSplitOwnership()
115 @*/
116 PetscErrorCode  MatSetSizes(Mat A, PetscInt m, PetscInt n, PetscInt M, PetscInt N)
117 {
118   PetscFunctionBegin;
119   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
120   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);
121   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);
122   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);
123   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);
124   A->rmap->n = m;
125   A->cmap->n = n;
126   A->rmap->N = M;
127   A->cmap->N = N;
128   PetscFunctionReturn(0);
129 }
130 
131 #undef __FUNCT__
132 #define __FUNCT__ "MatSetFromOptions"
133 /*@
134    MatSetFromOptions - Creates a matrix where the type is determined
135    from the options database. Generates a parallel MPI matrix if the
136    communicator has more than one processor.  The default matrix type is
137    AIJ, using the routines MatCreateSeqAIJ() and MatCreateAIJ() if
138    you do not select a type in the options database.
139 
140    Collective on Mat
141 
142    Input Parameter:
143 .  A - the matrix
144 
145    Options Database Keys:
146 +    -mat_type seqaij   - AIJ type, uses MatCreateSeqAIJ()
147 .    -mat_type mpiaij   - AIJ type, uses MatCreateAIJ()
148 .    -mat_type seqdense - dense type, uses MatCreateSeqDense()
149 .    -mat_type mpidense - dense type, uses MatCreateDense()
150 .    -mat_type seqbaij  - block AIJ type, uses MatCreateSeqBAIJ()
151 -    -mat_type mpibaij  - block AIJ type, uses MatCreateBAIJ()
152 
153    Even More Options Database Keys:
154    See the manpages for particular formats (e.g., MatCreateSeqAIJ())
155    for additional format-specific options.
156 
157    Level: beginner
158 
159 .keywords: matrix, create
160 
161 .seealso: MatCreateSeqAIJ((), MatCreateAIJ(),
162           MatCreateSeqDense(), MatCreateDense(),
163           MatCreateSeqBAIJ(), MatCreateBAIJ(),
164           MatCreateSeqSBAIJ(), MatCreateSBAIJ(),
165           MatConvert()
166 @*/
167 PetscErrorCode  MatSetFromOptions(Mat B)
168 {
169   PetscErrorCode ierr;
170   const char     *deft = MATAIJ;
171   char           type[256];
172   PetscBool      flg,set;
173 
174   PetscFunctionBegin;
175   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
176 
177   ierr = PetscObjectOptionsBegin((PetscObject)B);CHKERRQ(ierr);
178     ierr = PetscOptionsList("-mat_type","Matrix type","MatSetType",MatList,deft,type,256,&flg);CHKERRQ(ierr);
179     if (flg) {
180       ierr = MatSetType(B,type);CHKERRQ(ierr);
181     } else if (!((PetscObject)B)->type_name) {
182       ierr = MatSetType(B,deft);CHKERRQ(ierr);
183     }
184 
185     if (B->ops->setfromoptions) {
186       ierr = (*B->ops->setfromoptions)(B);CHKERRQ(ierr);
187     }
188 
189     flg = PETSC_FALSE;
190     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);
191     if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,flg);CHKERRQ(ierr);}
192     flg = PETSC_FALSE;
193     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);
194     if (set) {ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,flg);CHKERRQ(ierr);}
195 
196     /* process any options handlers added with PetscObjectAddOptionsHandler() */
197     ierr = PetscObjectProcessOptionsHandlers((PetscObject)B);CHKERRQ(ierr);
198   ierr = PetscOptionsEnd();CHKERRQ(ierr);
199 
200   PetscFunctionReturn(0);
201 }
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "MatXAIJSetPreallocation"
205 /*@
206    MatXAIJSetPreallocation - set preallocation for serial and parallel AIJ, BAIJ, and SBAIJ matrices
207 
208    Collective on Mat
209 
210    Input Arguments:
211 +  A - matrix being preallocated
212 .  bs - block size
213 .  dnnz - number of nonzero blocks per block row of diagonal part of parallel matrix
214 .  onnz - number of nonzero blocks per block row of off-diagonal part of parallel matrix
215 .  dnnzu - number of nonzero blocks per block row of upper-triangular part of diagonal part of parallel matrix
216 -  onnzu - number of nonzero blocks per block row of upper-triangular part of off-diagonal part of parallel matrix
217 
218    Level: beginner
219 
220 .seealso: MatSeqAIJSetPreallocation(), MatMPIAIJSetPreallocation(), MatSeqBAIJSetPreallocation(), MatMPIBAIJSetPreallocation(), MatSeqSBAIJSetPreallocation(), MatMPISBAIJSetPreallocation()
221 @*/
222 PetscErrorCode MatXAIJSetPreallocation(Mat A,PetscInt bs,const PetscInt *dnnz,const PetscInt *onnz,const PetscInt *dnnzu,const PetscInt *onnzu)
223 {
224   PetscErrorCode ierr;
225   void (*aij)(void);
226 
227   PetscFunctionBegin;
228   ierr = MatSeqBAIJSetPreallocation(A,bs,0,dnnz);CHKERRQ(ierr);
229   ierr = MatMPIBAIJSetPreallocation(A,bs,0,dnnz,0,onnz);CHKERRQ(ierr);
230   ierr = MatSeqSBAIJSetPreallocation(A,bs,0,dnnzu);CHKERRQ(ierr);
231   ierr = MatMPISBAIJSetPreallocation(A,bs,0,dnnzu,0,onnzu);CHKERRQ(ierr);
232   /*
233     In general, we have to do extra work to preallocate for scalar (AIJ) matrices so we check whether it will do any
234     good before going on with it.
235   */
236   ierr = PetscObjectQueryFunction((PetscObject)A,"MatMPIAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
237   if (!aij) {
238     ierr = PetscObjectQueryFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",&aij);CHKERRQ(ierr);
239   }
240   if (aij) {
241     if (bs == 1) {
242       ierr = MatSeqAIJSetPreallocation(A,0,dnnz);CHKERRQ(ierr);
243       ierr = MatMPIAIJSetPreallocation(A,0,dnnz,0,onnz);CHKERRQ(ierr);
244     } else {                    /* Convert block-row precallocation to scalar-row */
245       PetscInt i,m,*sdnnz,*sonnz;
246       ierr = MatGetLocalSize(A,&m,PETSC_NULL);CHKERRQ(ierr);
247       ierr = PetscMalloc2((!!dnnz)*m*bs,PetscInt,&sdnnz,(!!onnz)*m*bs,PetscInt,&sonnz);CHKERRQ(ierr);
248       for (i=0; i<m*bs; i++) {
249         if (dnnz) sdnnz[i] = dnnz[i/bs] * bs;
250         if (onnz) sonnz[i] = onnz[i/bs] * bs;
251       }
252       ierr = MatSeqAIJSetPreallocation(A,0,dnnz?sdnnz:PETSC_NULL);CHKERRQ(ierr);
253       ierr = MatMPIAIJSetPreallocation(A,0,dnnz?sdnnz:PETSC_NULL,0,onnz?sonnz:PETSC_NULL);CHKERRQ(ierr);
254       ierr = PetscFree2(sdnnz,sonnz);CHKERRQ(ierr);
255     }
256   }
257   ierr = MatSetBlockSize(A,bs);CHKERRQ(ierr);
258   PetscFunctionReturn(0);
259 }
260 
261 /*
262         Merges some information from Cs header to A; the C object is then destroyed
263 
264         This is somewhat different from MatHeaderReplace() it would be nice to merge the code
265 */
266 #undef __FUNCT__
267 #define __FUNCT__ "MatHeaderMerge"
268 PetscErrorCode MatHeaderMerge(Mat A,Mat C)
269 {
270   PetscErrorCode         ierr;
271   PetscInt               refct;
272   PetscOps               *Abops;
273   MatOps                 Aops;
274   char                   *mtype,*mname;
275   void                   *spptr;
276 
277   PetscFunctionBegin;
278   /* save the parts of A we need */
279   Abops = ((PetscObject)A)->bops;
280   Aops  = A->ops;
281   refct = ((PetscObject)A)->refct;
282   mtype = ((PetscObject)A)->type_name;
283   mname = ((PetscObject)A)->name;
284   spptr = A->spptr;
285 
286   /* zero these so the destroy below does not free them */
287   ((PetscObject)A)->type_name = 0;
288   ((PetscObject)A)->name      = 0;
289 
290   /* free all the interior data structures from mat */
291   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
292 
293   ierr = PetscFree(C->spptr);CHKERRQ(ierr);
294 
295   ierr = PetscLayoutDestroy(&A->rmap);CHKERRQ(ierr);
296   ierr = PetscLayoutDestroy(&A->cmap);CHKERRQ(ierr);
297   ierr = PetscFListDestroy(&((PetscObject)A)->qlist);CHKERRQ(ierr);
298   ierr = PetscOListDestroy(&((PetscObject)A)->olist);CHKERRQ(ierr);
299 
300   /* copy C over to A */
301   ierr  = PetscMemcpy(A,C,sizeof(struct _p_Mat));CHKERRQ(ierr);
302 
303   /* return the parts of A we saved */
304   ((PetscObject)A)->bops      = Abops;
305   A->ops                      = Aops;
306   ((PetscObject)A)->refct     = refct;
307   ((PetscObject)A)->type_name = mtype;
308   ((PetscObject)A)->name      = mname;
309   A->spptr                    = spptr;
310 
311   /* since these two are copied into A we do not want them destroyed in C */
312   ((PetscObject)C)->qlist = 0;
313   ((PetscObject)C)->olist = 0;
314   ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
315   PetscFunctionReturn(0);
316 }
317 /*
318         Replace A's header with that of C; the C object is then destroyed
319 
320         This is essentially code moved from MatDestroy()
321 
322         This is somewhat different from MatHeaderMerge() it would be nice to merge the code
323 */
324 #undef __FUNCT__
325 #define __FUNCT__ "MatHeaderReplace"
326 PetscErrorCode MatHeaderReplace(Mat A,Mat C)
327 {
328   PetscErrorCode ierr;
329   PetscInt refct;
330 
331   PetscFunctionBegin;
332   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
333   PetscValidHeaderSpecific(C,MAT_CLASSID,2);
334   if (A == C) PetscFunctionReturn(0);
335   PetscCheckSameComm(A,1,C,2);
336   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);
337 
338   /* free all the interior data structures from mat */
339   ierr = (*A->ops->destroy)(A);CHKERRQ(ierr);
340   ierr = PetscHeaderDestroy_Private((PetscObject)A);CHKERRQ(ierr);
341   ierr = PetscFree(A->ops);CHKERRQ(ierr);
342   ierr = PetscLayoutDestroy(&A->rmap);CHKERRQ(ierr);
343   ierr = PetscLayoutDestroy(&A->cmap);CHKERRQ(ierr);
344   ierr = PetscFree(A->spptr);CHKERRQ(ierr);
345 
346   /* copy C over to A */
347   refct = ((PetscObject)A)->refct;
348   ierr = PetscMemcpy(A,C,sizeof(struct _p_Mat));CHKERRQ(ierr);
349   ((PetscObject)A)->refct = refct;
350   ierr = PetscLogObjectDestroy((PetscObject)C);CHKERRQ(ierr);
351   ierr = PetscFree(C);CHKERRQ(ierr);
352   PetscFunctionReturn(0);
353 }
354