xref: /petsc/src/mat/interface/matreg.c (revision 55e7fe800d976e85ed2b5cd8bfdef564daa37bd9)
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 .keywords: Mat, MatType, set, method
33 
34 .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
35 @*/
36 PetscErrorCode  MatSetType(Mat mat, MatType matype)
37 {
38   PetscErrorCode ierr,(*r)(Mat);
39   PetscBool      sametype,found,subclass = PETSC_FALSE;
40   MatRootName    names = MatRootNameList;
41 
42   PetscFunctionBegin;
43   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
44 
45   while (names) {
46     ierr = PetscStrcmp(matype,names->rname,&found);CHKERRQ(ierr);
47     if (found) {
48       PetscMPIInt size;
49       ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
50       if (size == 1) matype = names->sname;
51       else matype = names->mname;
52       break;
53     }
54     names = names->next;
55   }
56 
57   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
58   if (sametype) PetscFunctionReturn(0);
59 
60   ierr =  PetscFunctionListFind(MatList,matype,&r);CHKERRQ(ierr);
61   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
62 
63   if (mat->assembled && ((PetscObject)mat)->type_name) {
64     ierr = PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);CHKERRQ(ierr);
65   }
66   if (subclass) {
67     ierr = MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
68     PetscFunctionReturn(0);
69   } if (mat->ops->destroy) {
70     /* free the old data structure if it existed */
71     ierr = (*mat->ops->destroy)(mat);CHKERRQ(ierr);
72     mat->ops->destroy = NULL;
73 
74     /* should these null spaces be removed? */
75     ierr = MatNullSpaceDestroy(&mat->nullsp);CHKERRQ(ierr);
76     ierr = MatNullSpaceDestroy(&mat->nearnullsp);CHKERRQ(ierr);
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   mat->preallocated  = PETSC_FALSE;
90   mat->assembled     = PETSC_FALSE;
91   mat->was_assembled = PETSC_FALSE;
92 
93   /* increase the state so that any code holding the current state knows the matrix has been changed */
94   mat->nonzerostate++;
95   ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr);
96 
97   /* create the new data structure */
98   ierr = (*r)(mat);CHKERRQ(ierr);
99   PetscFunctionReturn(0);
100 }
101 
102 /*@C
103    MatGetType - Gets the matrix type as a string from the matrix object.
104 
105    Not Collective
106 
107    Input Parameter:
108 .  mat - the matrix
109 
110    Output Parameter:
111 .  name - name of matrix type
112 
113    Level: intermediate
114 
115 .keywords: Mat, MatType, get, method, name
116 
117 .seealso: MatSetType()
118 @*/
119 PetscErrorCode  MatGetType(Mat mat,MatType *type)
120 {
121   PetscFunctionBegin;
122   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
123   PetscValidPointer(type,2);
124   *type = ((PetscObject)mat)->type_name;
125   PetscFunctionReturn(0);
126 }
127 
128 
129 /*@C
130   MatRegister -  - Adds a new matrix type
131 
132    Not Collective
133 
134    Input Parameters:
135 +  name - name of a new user-defined matrix type
136 -  routine_create - routine to create method context
137 
138    Notes:
139    MatRegister() may be called multiple times to add several user-defined solvers.
140 
141    Sample usage:
142 .vb
143    MatRegister("my_mat",MyMatCreate);
144 .ve
145 
146    Then, your solver can be chosen with the procedural interface via
147 $     MatSetType(Mat,"my_mat")
148    or at runtime via the option
149 $     -mat_type my_mat
150 
151    Level: advanced
152 
153 .keywords: Mat, register
154 
155 .seealso: MatRegisterAll()
156 
157 
158   Level: advanced
159 @*/
160 PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
161 {
162   PetscErrorCode ierr;
163 
164   PetscFunctionBegin;
165   ierr = MatInitializePackage();CHKERRQ(ierr);
166   ierr = PetscFunctionListAdd(&MatList,sname,function);CHKERRQ(ierr);
167   PetscFunctionReturn(0);
168 }
169 
170 MatRootName MatRootNameList = 0;
171 
172 /*@C
173       MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType()
174         and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
175         matrix.
176 
177   Input Parameters:
178 +     rname - the rootname, for example, MATAIJ
179 .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
180 -     mname - the name of the parallel matrix type, for example, MATMPIAIJ
181 
182   Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare()
183 
184   Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the
185       size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the
186       appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
187       confusing.
188 
189   Level: developer
190 
191 .seealso: PetscObjectBaseTypeCompare()
192 
193 @*/
194 PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
195 {
196   PetscErrorCode ierr;
197   MatRootName    names;
198 
199   PetscFunctionBegin;
200   ierr = PetscNew(&names);CHKERRQ(ierr);
201   ierr = PetscStrallocpy(rname,&names->rname);CHKERRQ(ierr);
202   ierr = PetscStrallocpy(sname,&names->sname);CHKERRQ(ierr);
203   ierr = PetscStrallocpy(mname,&names->mname);CHKERRQ(ierr);
204   if (!MatRootNameList) {
205     MatRootNameList = names;
206   } else {
207     MatRootName next = MatRootNameList;
208     while (next->next) next = next->next;
209     next->next = names;
210   }
211   PetscFunctionReturn(0);
212 }
213 
214 
215 
216 
217 
218 
219 
220