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