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