xref: /petsc/src/mat/interface/matreg.c (revision 2da392cc7c10228af19ad9843ce5155178acb644)
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);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   }
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   mat->preallocated  = PETSC_FALSE;
78   mat->assembled     = PETSC_FALSE;
79   mat->was_assembled = PETSC_FALSE;
80 
81   /*
82    Increment, rather than reset these: the object is logically the same, so its logging and
83    state is inherited.  Furthermore, resetting makes it possible for the same state to be
84    obtained with a different structure, confusing the PC.
85   */
86   mat->nonzerostate++;
87   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
88 
89   /* create the new data structure */
90   ierr = (*r)(mat);CHKERRQ(ierr);
91   PetscFunctionReturn(0);
92 }
93 
94 /*@C
95    MatGetType - Gets the matrix type as a string from the matrix object.
96 
97    Not Collective
98 
99    Input Parameter:
100 .  mat - the matrix
101 
102    Output Parameter:
103 .  name - name of matrix type
104 
105    Level: intermediate
106 
107 .seealso: MatSetType()
108 @*/
109 PetscErrorCode  MatGetType(Mat mat,MatType *type)
110 {
111   PetscFunctionBegin;
112   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
113   PetscValidPointer(type,2);
114   *type = ((PetscObject)mat)->type_name;
115   PetscFunctionReturn(0);
116 }
117 
118 /*@C
119    MatGetVecType - Gets the vector type used by the matrix object.
120 
121    Not Collective
122 
123    Input Parameter:
124 .  mat - the matrix
125 
126    Output Parameter:
127 .  name - name of vector type
128 
129    Level: intermediate
130 
131 .seealso: MatSetVecType()
132 @*/
133 PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
134 {
135   PetscFunctionBegin;
136   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
137   PetscValidPointer(vtype,2);
138   *vtype = mat->defaultvectype;
139   PetscFunctionReturn(0);
140 }
141 
142 /*@C
143    MatSetVecType - Set the vector type to be used for a matrix object
144 
145    Collective on Mat
146 
147    Input Parameters:
148 +  mat   - the matrix object
149 -  vtype - vector type
150 
151    Notes:
152      This is rarely needed in practice since each matrix object internally sets the proper vector type.
153 
154   Level: intermediate
155 
156 .seealso: VecSetType(), MatGetVecType()
157 @*/
158 PetscErrorCode MatSetVecType(Mat mat,VecType vtype)
159 {
160   PetscErrorCode ierr;
161 
162   PetscFunctionBegin;
163   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
164   ierr = PetscFree(mat->defaultvectype);CHKERRQ(ierr);
165   ierr = PetscStrallocpy(vtype,&mat->defaultvectype);CHKERRQ(ierr);
166   PetscFunctionReturn(0);
167 }
168 
169 /*@C
170   MatRegister -  - Adds a new matrix type
171 
172    Not Collective
173 
174    Input Parameters:
175 +  name - name of a new user-defined matrix type
176 -  routine_create - routine to create method context
177 
178    Notes:
179    MatRegister() may be called multiple times to add several user-defined solvers.
180 
181    Sample usage:
182 .vb
183    MatRegister("my_mat",MyMatCreate);
184 .ve
185 
186    Then, your solver can be chosen with the procedural interface via
187 $     MatSetType(Mat,"my_mat")
188    or at runtime via the option
189 $     -mat_type my_mat
190 
191    Level: advanced
192 
193 .seealso: MatRegisterAll()
194 
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