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