xref: /petsc/src/mat/interface/matreg.c (revision fa3789e02259308e44286a8852650b116d3beefe)
1 
2 /*
3      Mechanism for register PETSc matrix types
4 */
5 #include <petsc/private/matimpl.h>      /*I "petscmat.h" I*/
6 
7 PetscBool MatRegisterAllCalled = PETSC_FALSE;
8 
9 /*
10    Contains the list of registered Mat routines
11 */
12 PetscFunctionList MatList = NULL;
13 
14 /* MatGetRootType_Private - Gets the root type of the input matrix's type (e.g., MATAIJ for MATSEQAIJ)
15 
16    Not Collective
17 
18    Input Parameters:
19 .  mat      - the input matrix, could be sequential or MPI
20 
21    Output Parameters:
22 .  rootType  - the root matrix type
23 
24    Level: developer
25 
26 .seealso: MatGetType(), MatSetType(), MatType, Mat
27 */
28 PetscErrorCode MatGetRootType_Private(Mat mat, MatType *rootType)
29 {
30   PetscErrorCode ierr;
31   PetscBool      found = PETSC_FALSE;
32   MatRootName    names = MatRootNameList;
33   MatType        inType;
34 
35   PetscFunctionBegin;
36   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
37   ierr = MatGetType(mat,&inType);CHKERRQ(ierr);
38   while (names) {
39     ierr = PetscStrcmp(inType,names->mname,&found);CHKERRQ(ierr);
40     if (!found) { ierr = PetscStrcmp(inType,names->sname,&found);CHKERRQ(ierr); }
41     if (found) {
42       found     = PETSC_TRUE;
43       *rootType = names->rname;
44       break;
45     }
46     names = names->next;
47   }
48   if (!found) *rootType = inType;
49   PetscFunctionReturn(0);
50 }
51 
52 /*@C
53    MatSetType - Builds matrix object for a particular matrix type
54 
55    Collective on Mat
56 
57    Input Parameters:
58 +  mat      - the matrix object
59 -  matype   - matrix type
60 
61    Options Database Key:
62 .  -mat_type  <method> - Sets the type; use -help for a list
63     of available methods (for instance, seqaij)
64 
65    Notes:
66    See "${PETSC_DIR}/include/petscmat.h" for available methods
67 
68   Level: intermediate
69 
70 .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
71 @*/
72 PetscErrorCode  MatSetType(Mat mat, MatType matype)
73 {
74   PetscErrorCode ierr,(*r)(Mat);
75   PetscBool      sametype,found,subclass = PETSC_FALSE;
76   MatRootName    names = MatRootNameList;
77 
78   PetscFunctionBegin;
79   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
80 
81   while (names) {
82     ierr = PetscStrcmp(matype,names->rname,&found);CHKERRQ(ierr);
83     if (found) {
84       PetscMPIInt size;
85       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRMPI(ierr);
86       if (size == 1) matype = names->sname;
87       else matype = names->mname;
88       break;
89     }
90     names = names->next;
91   }
92 
93   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
94   if (sametype) PetscFunctionReturn(0);
95 
96   ierr = PetscFunctionListFind(MatList,matype,&r);CHKERRQ(ierr);
97   PetscCheckFalse(!r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
98 
99   if (mat->assembled && ((PetscObject)mat)->type_name) {
100     ierr = PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);CHKERRQ(ierr);
101   }
102   if (subclass) {
103     ierr = MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
104     PetscFunctionReturn(0);
105   }
106   if (mat->ops->destroy) {
107     /* free the old data structure if it existed */
108     ierr = (*mat->ops->destroy)(mat);CHKERRQ(ierr);
109     mat->ops->destroy = NULL;
110 
111     /* should these null spaces be removed? */
112     ierr = MatNullSpaceDestroy(&mat->nullsp);CHKERRQ(ierr);
113     ierr = MatNullSpaceDestroy(&mat->nearnullsp);CHKERRQ(ierr);
114   }
115   ierr = PetscMemzero(mat->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
116   mat->preallocated  = PETSC_FALSE;
117   mat->assembled     = PETSC_FALSE;
118   mat->was_assembled = PETSC_FALSE;
119 
120   /*
121    Increment, rather than reset these: the object is logically the same, so its logging and
122    state is inherited.  Furthermore, resetting makes it possible for the same state to be
123    obtained with a different structure, confusing the PC.
124   */
125   mat->nonzerostate++;
126   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
127 
128   /* create the new data structure */
129   ierr = (*r)(mat);CHKERRQ(ierr);
130   PetscFunctionReturn(0);
131 }
132 
133 /*@C
134    MatGetType - Gets the matrix type as a string from the matrix object.
135 
136    Not Collective
137 
138    Input Parameter:
139 .  mat - the matrix
140 
141    Output Parameter:
142 .  name - name of matrix type
143 
144    Level: intermediate
145 
146 .seealso: MatSetType()
147 @*/
148 PetscErrorCode  MatGetType(Mat mat,MatType *type)
149 {
150   PetscFunctionBegin;
151   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
152   PetscValidPointer(type,2);
153   *type = ((PetscObject)mat)->type_name;
154   PetscFunctionReturn(0);
155 }
156 
157 /*@C
158    MatGetVecType - Gets the vector type used by the matrix object.
159 
160    Not Collective
161 
162    Input Parameter:
163 .  mat - the matrix
164 
165    Output Parameter:
166 .  name - name of vector type
167 
168    Level: intermediate
169 
170 .seealso: MatSetVecType()
171 @*/
172 PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
173 {
174   PetscFunctionBegin;
175   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
176   PetscValidPointer(vtype,2);
177   *vtype = mat->defaultvectype;
178   PetscFunctionReturn(0);
179 }
180 
181 /*@C
182    MatSetVecType - Set the vector type to be used for a matrix object
183 
184    Collective on Mat
185 
186    Input Parameters:
187 +  mat   - the matrix object
188 -  vtype - vector type
189 
190    Notes:
191      This is rarely needed in practice since each matrix object internally sets the proper vector type.
192 
193   Level: intermediate
194 
195 .seealso: VecSetType(), MatGetVecType()
196 @*/
197 PetscErrorCode MatSetVecType(Mat mat,VecType vtype)
198 {
199   PetscErrorCode ierr;
200 
201   PetscFunctionBegin;
202   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
203   ierr = PetscFree(mat->defaultvectype);CHKERRQ(ierr);
204   ierr = PetscStrallocpy(vtype,&mat->defaultvectype);CHKERRQ(ierr);
205   PetscFunctionReturn(0);
206 }
207 
208 /*@C
209   MatRegister -  - Adds a new matrix type
210 
211    Not Collective
212 
213    Input Parameters:
214 +  name - name of a new user-defined matrix type
215 -  routine_create - routine to create method context
216 
217    Notes:
218    MatRegister() may be called multiple times to add several user-defined solvers.
219 
220    Sample usage:
221 .vb
222    MatRegister("my_mat",MyMatCreate);
223 .ve
224 
225    Then, your solver can be chosen with the procedural interface via
226 $     MatSetType(Mat,"my_mat")
227    or at runtime via the option
228 $     -mat_type my_mat
229 
230    Level: advanced
231 
232 .seealso: MatRegisterAll()
233 
234   Level: advanced
235 @*/
236 PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
237 {
238   PetscErrorCode ierr;
239 
240   PetscFunctionBegin;
241   ierr = MatInitializePackage();CHKERRQ(ierr);
242   ierr = PetscFunctionListAdd(&MatList,sname,function);CHKERRQ(ierr);
243   PetscFunctionReturn(0);
244 }
245 
246 MatRootName MatRootNameList = NULL;
247 
248 /*@C
249       MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType()
250         and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
251         matrix.
252 
253   Input Parameters:
254 +     rname - the rootname, for example, MATAIJ
255 .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
256 -     mname - the name of the parallel matrix type, for example, MATMPIAIJ
257 
258   Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare()
259 
260   Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the
261       size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the
262       appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
263       confusing.
264 
265   Level: developer
266 
267 .seealso: PetscObjectBaseTypeCompare()
268 
269 @*/
270 PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
271 {
272   PetscErrorCode ierr;
273   MatRootName    names;
274 
275   PetscFunctionBegin;
276   ierr = PetscNew(&names);CHKERRQ(ierr);
277   ierr = PetscStrallocpy(rname,&names->rname);CHKERRQ(ierr);
278   ierr = PetscStrallocpy(sname,&names->sname);CHKERRQ(ierr);
279   ierr = PetscStrallocpy(mname,&names->mname);CHKERRQ(ierr);
280   if (!MatRootNameList) {
281     MatRootNameList = names;
282   } else {
283     MatRootName next = MatRootNameList;
284     while (next->next) next = next->next;
285     next->next = names;
286   }
287   PetscFunctionReturn(0);
288 }
289