xref: /petsc/src/mat/interface/matreg.c (revision 030f984af8d8bb4c203755d35bded3c05b3d83ce)
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 /*@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);CHKERRMPI(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   }
68   if (mat->ops->destroy) {
69     /* free the old data structure if it existed */
70     ierr = (*mat->ops->destroy)(mat);CHKERRQ(ierr);
71     mat->ops->destroy = NULL;
72 
73     /* should these null spaces be removed? */
74     ierr = MatNullSpaceDestroy(&mat->nullsp);CHKERRQ(ierr);
75     ierr = MatNullSpaceDestroy(&mat->nearnullsp);CHKERRQ(ierr);
76   }
77   ierr = PetscMemzero(mat->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
78   mat->preallocated  = PETSC_FALSE;
79   mat->assembled     = PETSC_FALSE;
80   mat->was_assembled = PETSC_FALSE;
81 
82   /*
83    Increment, rather than reset these: the object is logically the same, so its logging and
84    state is inherited.  Furthermore, resetting makes it possible for the same state to be
85    obtained with a different structure, confusing the PC.
86   */
87   mat->nonzerostate++;
88   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
89 
90   /* create the new data structure */
91   ierr = (*r)(mat);CHKERRQ(ierr);
92   PetscFunctionReturn(0);
93 }
94 
95 /*@C
96    MatGetType - Gets the matrix type as a string from the matrix object.
97 
98    Not Collective
99 
100    Input Parameter:
101 .  mat - the matrix
102 
103    Output Parameter:
104 .  name - name of matrix type
105 
106    Level: intermediate
107 
108 .seealso: MatSetType()
109 @*/
110 PetscErrorCode  MatGetType(Mat mat,MatType *type)
111 {
112   PetscFunctionBegin;
113   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
114   PetscValidPointer(type,2);
115   *type = ((PetscObject)mat)->type_name;
116   PetscFunctionReturn(0);
117 }
118 
119 /*@C
120    MatGetVecType - Gets the vector type used by the matrix object.
121 
122    Not Collective
123 
124    Input Parameter:
125 .  mat - the matrix
126 
127    Output Parameter:
128 .  name - name of vector type
129 
130    Level: intermediate
131 
132 .seealso: MatSetVecType()
133 @*/
134 PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
135 {
136   PetscFunctionBegin;
137   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
138   PetscValidPointer(vtype,2);
139   *vtype = mat->defaultvectype;
140   PetscFunctionReturn(0);
141 }
142 
143 /*@C
144    MatSetVecType - Set the vector type to be used for a matrix object
145 
146    Collective on Mat
147 
148    Input Parameters:
149 +  mat   - the matrix object
150 -  vtype - vector type
151 
152    Notes:
153      This is rarely needed in practice since each matrix object internally sets the proper vector type.
154 
155   Level: intermediate
156 
157 .seealso: VecSetType(), MatGetVecType()
158 @*/
159 PetscErrorCode MatSetVecType(Mat mat,VecType vtype)
160 {
161   PetscErrorCode ierr;
162 
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
165   ierr = PetscFree(mat->defaultvectype);CHKERRQ(ierr);
166   ierr = PetscStrallocpy(vtype,&mat->defaultvectype);CHKERRQ(ierr);
167   PetscFunctionReturn(0);
168 }
169 
170 /*@C
171   MatRegister -  - Adds a new matrix type
172 
173    Not Collective
174 
175    Input Parameters:
176 +  name - name of a new user-defined matrix type
177 -  routine_create - routine to create method context
178 
179    Notes:
180    MatRegister() may be called multiple times to add several user-defined solvers.
181 
182    Sample usage:
183 .vb
184    MatRegister("my_mat",MyMatCreate);
185 .ve
186 
187    Then, your solver can be chosen with the procedural interface via
188 $     MatSetType(Mat,"my_mat")
189    or at runtime via the option
190 $     -mat_type my_mat
191 
192    Level: advanced
193 
194 .seealso: MatRegisterAll()
195 
196   Level: advanced
197 @*/
198 PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
199 {
200   PetscErrorCode ierr;
201 
202   PetscFunctionBegin;
203   ierr = MatInitializePackage();CHKERRQ(ierr);
204   ierr = PetscFunctionListAdd(&MatList,sname,function);CHKERRQ(ierr);
205   PetscFunctionReturn(0);
206 }
207 
208 MatRootName MatRootNameList = NULL;
209 
210 /*@C
211       MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType()
212         and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
213         matrix.
214 
215   Input Parameters:
216 +     rname - the rootname, for example, MATAIJ
217 .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
218 -     mname - the name of the parallel matrix type, for example, MATMPIAIJ
219 
220   Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare()
221 
222   Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the
223       size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the
224       appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
225       confusing.
226 
227   Level: developer
228 
229 .seealso: PetscObjectBaseTypeCompare()
230 
231 @*/
232 PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
233 {
234   PetscErrorCode ierr;
235   MatRootName    names;
236 
237   PetscFunctionBegin;
238   ierr = PetscNew(&names);CHKERRQ(ierr);
239   ierr = PetscStrallocpy(rname,&names->rname);CHKERRQ(ierr);
240   ierr = PetscStrallocpy(sname,&names->sname);CHKERRQ(ierr);
241   ierr = PetscStrallocpy(mname,&names->mname);CHKERRQ(ierr);
242   if (!MatRootNameList) {
243     MatRootNameList = names;
244   } else {
245     MatRootName next = MatRootNameList;
246     while (next->next) next = next->next;
247     next->next = names;
248   }
249   PetscFunctionReturn(0);
250 }
251