xref: /petsc/src/mat/interface/matreg.c (revision 63f3c55c12ae2f190c391f6df6c540efe018a44a)
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 
125 /*@C
126   MatRegister -  - Adds a new matrix type
127 
128    Not Collective
129 
130    Input Parameters:
131 +  name - name of a new user-defined matrix type
132 -  routine_create - routine to create method context
133 
134    Notes:
135    MatRegister() may be called multiple times to add several user-defined solvers.
136 
137    Sample usage:
138 .vb
139    MatRegister("my_mat",MyMatCreate);
140 .ve
141 
142    Then, your solver can be chosen with the procedural interface via
143 $     MatSetType(Mat,"my_mat")
144    or at runtime via the option
145 $     -mat_type my_mat
146 
147    Level: advanced
148 
149 .seealso: MatRegisterAll()
150 
151 
152   Level: advanced
153 @*/
154 PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
155 {
156   PetscErrorCode ierr;
157 
158   PetscFunctionBegin;
159   ierr = MatInitializePackage();CHKERRQ(ierr);
160   ierr = PetscFunctionListAdd(&MatList,sname,function);CHKERRQ(ierr);
161   PetscFunctionReturn(0);
162 }
163 
164 MatRootName MatRootNameList = 0;
165 
166 /*@C
167       MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType()
168         and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
169         matrix.
170 
171   Input Parameters:
172 +     rname - the rootname, for example, MATAIJ
173 .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
174 -     mname - the name of the parallel matrix type, for example, MATMPIAIJ
175 
176   Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare()
177 
178   Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the
179       size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the
180       appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
181       confusing.
182 
183   Level: developer
184 
185 .seealso: PetscObjectBaseTypeCompare()
186 
187 @*/
188 PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
189 {
190   PetscErrorCode ierr;
191   MatRootName    names;
192 
193   PetscFunctionBegin;
194   ierr = PetscNew(&names);CHKERRQ(ierr);
195   ierr = PetscStrallocpy(rname,&names->rname);CHKERRQ(ierr);
196   ierr = PetscStrallocpy(sname,&names->sname);CHKERRQ(ierr);
197   ierr = PetscStrallocpy(mname,&names->mname);CHKERRQ(ierr);
198   if (!MatRootNameList) {
199     MatRootNameList = names;
200   } else {
201     MatRootName next = MatRootNameList;
202     while (next->next) next = next->next;
203     next->next = names;
204   }
205   PetscFunctionReturn(0);
206 }
207 
208 
209 
210 
211 
212 
213 
214