Actual source code: matreg.c
2: /*
3: Mechanism for register PETSc matrix types
4: */
5: #include <petsc/private/matimpl.h>
7: PetscBool MatRegisterAllCalled = PETSC_FALSE;
9: /*
10: Contains the list of registered Mat routines
11: */
12: PetscFunctionList MatList = NULL;
14: /* MatGetRootType_Private - Gets the root type of the input matrix's type (e.g., MATAIJ for MATSEQAIJ)
16: Not Collective
18: Input Parameters:
19: . mat - the input matrix, could be sequential or MPI
21: Output Parameters:
22: . rootType - the root matrix type
24: Level: developer
26: .seealso: MatGetType(), MatSetType(), MatType, Mat
27: */
28: PetscErrorCode MatGetRootType_Private(Mat mat, MatType *rootType)
29: {
30: PetscBool found = PETSC_FALSE;
31: MatRootName names = MatRootNameList;
32: MatType inType;
35: MatGetType(mat,&inType);
36: while (names) {
37: PetscStrcmp(inType,names->mname,&found);
38: if (!found) PetscStrcmp(inType,names->sname,&found);
39: if (found) {
40: found = PETSC_TRUE;
41: *rootType = names->rname;
42: break;
43: }
44: names = names->next;
45: }
46: if (!found) *rootType = inType;
47: return 0;
48: }
50: /*@C
51: MatSetType - Builds matrix object for a particular matrix type
53: Collective on Mat
55: Input Parameters:
56: + mat - the matrix object
57: - matype - matrix type
59: Options Database Key:
60: . -mat_type <method> - Sets the type; use -help for a list
61: of available methods (for instance, seqaij)
63: Notes:
64: See "${PETSC_DIR}/include/petscmat.h" for available methods
66: Level: intermediate
68: .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
69: @*/
70: PetscErrorCode MatSetType(Mat mat, MatType matype)
71: {
72: PetscBool sametype,found,subclass = PETSC_FALSE;
73: MatRootName names = MatRootNameList;
74: PetscErrorCode (*r)(Mat);
78: while (names) {
79: PetscStrcmp(matype,names->rname,&found);
80: if (found) {
81: PetscMPIInt size;
82: MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);
83: if (size == 1) matype = names->sname;
84: else matype = names->mname;
85: break;
86: }
87: names = names->next;
88: }
90: PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);
91: if (sametype) return 0;
93: PetscFunctionListFind(MatList,matype,&r);
96: if (mat->assembled && ((PetscObject)mat)->type_name) PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);
97: if (subclass) {
98: MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);
99: return 0;
100: }
101: if (mat->ops->destroy) {
102: /* free the old data structure if it existed */
103: (*mat->ops->destroy)(mat);
104: mat->ops->destroy = NULL;
106: /* should these null spaces be removed? */
107: MatNullSpaceDestroy(&mat->nullsp);
108: MatNullSpaceDestroy(&mat->nearnullsp);
109: }
110: PetscMemzero(mat->ops,sizeof(struct _MatOps));
111: mat->preallocated = PETSC_FALSE;
112: mat->assembled = PETSC_FALSE;
113: mat->was_assembled = PETSC_FALSE;
115: /*
116: Increment, rather than reset these: the object is logically the same, so its logging and
117: state is inherited. Furthermore, resetting makes it possible for the same state to be
118: obtained with a different structure, confusing the PC.
119: */
120: mat->nonzerostate++;
121: PetscObjectStateIncrease((PetscObject)mat);
123: /* create the new data structure */
124: (*r)(mat);
125: return 0;
126: }
128: /*@C
129: MatGetType - Gets the matrix type as a string from the matrix object.
131: Not Collective
133: Input Parameter:
134: . mat - the matrix
136: Output Parameter:
137: . name - name of matrix type
139: Level: intermediate
141: .seealso: MatSetType()
142: @*/
143: PetscErrorCode MatGetType(Mat mat,MatType *type)
144: {
147: *type = ((PetscObject)mat)->type_name;
148: return 0;
149: }
151: /*@C
152: MatGetVecType - Gets the vector type used by the matrix object.
154: Not Collective
156: Input Parameter:
157: . mat - the matrix
159: Output Parameter:
160: . name - name of vector type
162: Level: intermediate
164: .seealso: MatSetVecType()
165: @*/
166: PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
167: {
170: *vtype = mat->defaultvectype;
171: return 0;
172: }
174: /*@C
175: MatSetVecType - Set the vector type to be used for a matrix object
177: Collective on Mat
179: Input Parameters:
180: + mat - the matrix object
181: - vtype - vector type
183: Notes:
184: This is rarely needed in practice since each matrix object internally sets the proper vector type.
186: Level: intermediate
188: .seealso: VecSetType(), MatGetVecType()
189: @*/
190: PetscErrorCode MatSetVecType(Mat mat,VecType vtype)
191: {
193: PetscFree(mat->defaultvectype);
194: PetscStrallocpy(vtype,&mat->defaultvectype);
195: return 0;
196: }
198: /*@C
199: MatRegister - - Adds a new matrix type
201: Not Collective
203: Input Parameters:
204: + name - name of a new user-defined matrix type
205: - routine_create - routine to create method context
207: Notes:
208: MatRegister() may be called multiple times to add several user-defined solvers.
210: Sample usage:
211: .vb
212: MatRegister("my_mat",MyMatCreate);
213: .ve
215: Then, your solver can be chosen with the procedural interface via
216: $ MatSetType(Mat,"my_mat")
217: or at runtime via the option
218: $ -mat_type my_mat
220: Level: advanced
222: .seealso: MatRegisterAll()
224: Level: advanced
225: @*/
226: PetscErrorCode MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
227: {
228: MatInitializePackage();
229: PetscFunctionListAdd(&MatList,sname,function);
230: return 0;
231: }
233: MatRootName MatRootNameList = NULL;
235: /*@C
236: MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType()
237: and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
238: matrix.
240: Input Parameters:
241: + rname - the rootname, for example, MATAIJ
242: . sname - the name of the sequential matrix type, for example, MATSEQAIJ
243: - mname - the name of the parallel matrix type, for example, MATMPIAIJ
245: Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare()
247: Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the
248: size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the
249: appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
250: confusing.
252: Level: developer
254: .seealso: PetscObjectBaseTypeCompare()
256: @*/
257: PetscErrorCode MatRegisterRootName(const char rname[],const char sname[],const char mname[])
258: {
259: MatRootName names;
261: PetscNew(&names);
262: PetscStrallocpy(rname,&names->rname);
263: PetscStrallocpy(sname,&names->sname);
264: PetscStrallocpy(mname,&names->mname);
265: if (!MatRootNameList) {
266: MatRootNameList = names;
267: } else {
268: MatRootName next = MatRootNameList;
269: while (next->next) next = next->next;
270: next->next = names;
271: }
272: return 0;
273: }