xref: /petsc/src/mat/interface/matreg.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
1be1d678aSKris Buschelman 
27e14e8a7SBarry Smith /*
399cd5145SBarry Smith      Mechanism for register PETSc matrix types
47e14e8a7SBarry Smith */
5af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
67e14e8a7SBarry Smith 
7ace3abfcSBarry Smith PetscBool MatRegisterAllCalled = PETSC_FALSE;
87e14e8a7SBarry Smith 
97e14e8a7SBarry Smith /*
1099cd5145SBarry Smith    Contains the list of registered Mat routines
117e14e8a7SBarry Smith */
12f4259b30SLisandro Dalcin PetscFunctionList MatList = NULL;
137e14e8a7SBarry Smith 
142c99ec25SJunchao Zhang /* MatGetRootType_Private - Gets the root type of the input matrix's type (e.g., MATAIJ for MATSEQAIJ)
152c99ec25SJunchao Zhang 
162c99ec25SJunchao Zhang    Not Collective
172c99ec25SJunchao Zhang 
182c99ec25SJunchao Zhang    Input Parameters:
192c99ec25SJunchao Zhang .  mat      - the input matrix, could be sequential or MPI
202c99ec25SJunchao Zhang 
212c99ec25SJunchao Zhang    Output Parameters:
222c99ec25SJunchao Zhang .  rootType  - the root matrix type
232c99ec25SJunchao Zhang 
242c99ec25SJunchao Zhang    Level: developer
252c99ec25SJunchao Zhang 
26db781477SPatrick Sanan .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat`
272c99ec25SJunchao Zhang */
28*9371c9d4SSatish Balay PetscErrorCode MatGetRootType_Private(Mat mat, MatType *rootType) {
292c99ec25SJunchao Zhang   PetscBool   found = PETSC_FALSE;
302c99ec25SJunchao Zhang   MatRootName names = MatRootNameList;
312c99ec25SJunchao Zhang   MatType     inType;
322c99ec25SJunchao Zhang 
332c99ec25SJunchao Zhang   PetscFunctionBegin;
342c99ec25SJunchao Zhang   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
359566063dSJacob Faibussowitsch   PetscCall(MatGetType(mat, &inType));
362c99ec25SJunchao Zhang   while (names) {
379566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(inType, names->mname, &found));
389566063dSJacob Faibussowitsch     if (!found) PetscCall(PetscStrcmp(inType, names->sname, &found));
392c99ec25SJunchao Zhang     if (found) {
402c99ec25SJunchao Zhang       found     = PETSC_TRUE;
412c99ec25SJunchao Zhang       *rootType = names->rname;
422c99ec25SJunchao Zhang       break;
432c99ec25SJunchao Zhang     }
442c99ec25SJunchao Zhang     names = names->next;
452c99ec25SJunchao Zhang   }
462c99ec25SJunchao Zhang   if (!found) *rootType = inType;
472c99ec25SJunchao Zhang   PetscFunctionReturn(0);
482c99ec25SJunchao Zhang }
492c99ec25SJunchao Zhang 
50ac81f253SRichard Tran Mills /* MatGetMPIMatType_Private - Gets the MPI type corresponding to the input matrix's type (e.g., MATMPIAIJ for MATSEQAIJ)
51ac81f253SRichard Tran Mills 
52ac81f253SRichard Tran Mills    Not Collective
53ac81f253SRichard Tran Mills 
54ac81f253SRichard Tran Mills    Input Parameters:
55ac81f253SRichard Tran Mills .  mat      - the input matrix, could be sequential or MPI
56ac81f253SRichard Tran Mills 
57ac81f253SRichard Tran Mills    Output Parameters:
58ac81f253SRichard Tran Mills .  MPIType  - the parallel (MPI) matrix type
59ac81f253SRichard Tran Mills 
60ac81f253SRichard Tran Mills    Level: developer
61ac81f253SRichard Tran Mills 
62ac81f253SRichard Tran Mills .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat`
63ac81f253SRichard Tran Mills */
64*9371c9d4SSatish Balay PetscErrorCode MatGetMPIMatType_Private(Mat mat, MatType *MPIType) {
65ac81f253SRichard Tran Mills   PetscBool   found = PETSC_FALSE;
66ac81f253SRichard Tran Mills   MatRootName names = MatRootNameList;
67ac81f253SRichard Tran Mills   MatType     inType;
68ac81f253SRichard Tran Mills 
69ac81f253SRichard Tran Mills   PetscFunctionBegin;
70ac81f253SRichard Tran Mills   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
71ac81f253SRichard Tran Mills   PetscCall(MatGetType(mat, &inType));
72ac81f253SRichard Tran Mills   while (names) {
73ac81f253SRichard Tran Mills     PetscCall(PetscStrcmp(inType, names->sname, &found));
74ac81f253SRichard Tran Mills     if (!found) PetscCall(PetscStrcmp(inType, names->mname, &found));
75ac81f253SRichard Tran Mills     if (!found) PetscCall(PetscStrcmp(inType, names->rname, &found));
76ac81f253SRichard Tran Mills     if (found) {
77ac81f253SRichard Tran Mills       found    = PETSC_TRUE;
78ac81f253SRichard Tran Mills       *MPIType = names->mname;
79ac81f253SRichard Tran Mills       break;
80ac81f253SRichard Tran Mills     }
81ac81f253SRichard Tran Mills     names = names->next;
82ac81f253SRichard Tran Mills   }
83ac81f253SRichard Tran Mills   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_SUP, "No corresponding parallel (MPI) type for this matrix");
84ac81f253SRichard Tran Mills   PetscFunctionReturn(0);
85ac81f253SRichard Tran Mills }
86ac81f253SRichard Tran Mills 
877e14e8a7SBarry Smith /*@C
8899cd5145SBarry Smith    MatSetType - Builds matrix object for a particular matrix type
897e14e8a7SBarry Smith 
9099cd5145SBarry Smith    Collective on Mat
917e14e8a7SBarry Smith 
927e14e8a7SBarry Smith    Input Parameters:
9399cd5145SBarry Smith +  mat      - the matrix object
9499cd5145SBarry Smith -  matype   - matrix type
957e14e8a7SBarry Smith 
967e14e8a7SBarry Smith    Options Database Key:
9799cd5145SBarry Smith .  -mat_type  <method> - Sets the type; use -help for a list
9899cd5145SBarry Smith     of available methods (for instance, seqaij)
997e14e8a7SBarry Smith 
1007e14e8a7SBarry Smith    Notes:
10199cd5145SBarry Smith    See "${PETSC_DIR}/include/petscmat.h" for available methods
1027e14e8a7SBarry Smith 
1037e14e8a7SBarry Smith   Level: intermediate
1047e14e8a7SBarry Smith 
105db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat`
1067e14e8a7SBarry Smith @*/
107*9371c9d4SSatish Balay PetscErrorCode MatSetType(Mat mat, MatType matype) {
1083dcd2dd8SBarry Smith   PetscBool   sametype, found, subclass = PETSC_FALSE;
10923bebc0bSBarry Smith   MatRootName names = MatRootNameList;
1105f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Mat);
1117e14e8a7SBarry Smith 
1127e14e8a7SBarry Smith   PetscFunctionBegin;
1130700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
114117016b1SBarry Smith 
11501bebe75SBarry Smith   while (names) {
1169566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(matype, names->rname, &found));
11701bebe75SBarry Smith     if (found) {
11801bebe75SBarry Smith       PetscMPIInt size;
1199566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
12001bebe75SBarry Smith       if (size == 1) matype = names->sname;
12101bebe75SBarry Smith       else matype = names->mname;
12201bebe75SBarry Smith       break;
12301bebe75SBarry Smith     }
12401bebe75SBarry Smith     names = names->next;
12501bebe75SBarry Smith   }
12601bebe75SBarry Smith 
1279566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype));
12892ff6ae8SBarry Smith   if (sametype) PetscFunctionReturn(0);
12992ff6ae8SBarry Smith 
1309566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(MatList, matype, &r));
1315f80ce2aSJacob Faibussowitsch   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype);
1327e14e8a7SBarry Smith 
1339566063dSJacob Faibussowitsch   if (mat->assembled && ((PetscObject)mat)->type_name) PetscCall(PetscStrbeginswith(matype, ((PetscObject)mat)->type_name, &subclass));
1343dcd2dd8SBarry Smith   if (subclass) {
1359566063dSJacob Faibussowitsch     PetscCall(MatConvert(mat, matype, MAT_INPLACE_MATRIX, &mat));
1363dcd2dd8SBarry Smith     PetscFunctionReturn(0);
13728fc0bbcSJose E. Roman   }
138dbbe0bcdSBarry Smith   PetscTryTypeMethod(mat, destroy);
1390298fd71SBarry Smith   mat->ops->destroy = NULL;
14082e0f345SBarry Smith 
14132e7c8b0SBarry Smith   /* should these null spaces be removed? */
1429566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
1439566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
144dbbe0bcdSBarry Smith 
1459566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(mat->ops, sizeof(struct _MatOps)));
14682e0f345SBarry Smith   mat->preallocated  = PETSC_FALSE;
14782e0f345SBarry Smith   mat->assembled     = PETSC_FALSE;
14882e0f345SBarry Smith   mat->was_assembled = PETSC_FALSE;
14982e0f345SBarry Smith 
15082e0f345SBarry Smith   /*
15182e0f345SBarry Smith    Increment, rather than reset these: the object is logically the same, so its logging and
15282e0f345SBarry Smith    state is inherited.  Furthermore, resetting makes it possible for the same state to be
15382e0f345SBarry Smith    obtained with a different structure, confusing the PC.
15482e0f345SBarry Smith   */
15532e7c8b0SBarry Smith   mat->nonzerostate++;
1569566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
157a2ec6df8SKris Buschelman 
15835d8aa7fSBarry Smith   /* create the new data structure */
1599566063dSJacob Faibussowitsch   PetscCall((*r)(mat));
1607e14e8a7SBarry Smith   PetscFunctionReturn(0);
1617e14e8a7SBarry Smith }
1627e14e8a7SBarry Smith 
1637e14e8a7SBarry Smith /*@C
164f87b78b8SBarry Smith    MatGetType - Gets the matrix type as a string from the matrix object.
1657e14e8a7SBarry Smith 
1667e14e8a7SBarry Smith    Not Collective
1677e14e8a7SBarry Smith 
1687e14e8a7SBarry Smith    Input Parameter:
16999cd5145SBarry Smith .  mat - the matrix
1707e14e8a7SBarry Smith 
1717e14e8a7SBarry Smith    Output Parameter:
17299cd5145SBarry Smith .  name - name of matrix type
1737e14e8a7SBarry Smith 
1747e14e8a7SBarry Smith    Level: intermediate
1757e14e8a7SBarry Smith 
176db781477SPatrick Sanan .seealso: `MatSetType()`
1777e14e8a7SBarry Smith @*/
178*9371c9d4SSatish Balay PetscErrorCode MatGetType(Mat mat, MatType *type) {
1797e14e8a7SBarry Smith   PetscFunctionBegin;
1800700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
181c4e43342SLisandro Dalcin   PetscValidPointer(type, 2);
1827adad957SLisandro Dalcin   *type = ((PetscObject)mat)->type_name;
1837e14e8a7SBarry Smith   PetscFunctionReturn(0);
1847e14e8a7SBarry Smith }
1857e14e8a7SBarry Smith 
1860d229a57SStefano Zampini /*@C
1870d229a57SStefano Zampini    MatGetVecType - Gets the vector type used by the matrix object.
1880d229a57SStefano Zampini 
1890d229a57SStefano Zampini    Not Collective
1900d229a57SStefano Zampini 
1910d229a57SStefano Zampini    Input Parameter:
1920d229a57SStefano Zampini .  mat - the matrix
1930d229a57SStefano Zampini 
1940d229a57SStefano Zampini    Output Parameter:
1950d229a57SStefano Zampini .  name - name of vector type
1960d229a57SStefano Zampini 
1970d229a57SStefano Zampini    Level: intermediate
1980d229a57SStefano Zampini 
199db781477SPatrick Sanan .seealso: `MatSetVecType()`
2000d229a57SStefano Zampini @*/
201*9371c9d4SSatish Balay PetscErrorCode MatGetVecType(Mat mat, VecType *vtype) {
2020d229a57SStefano Zampini   PetscFunctionBegin;
2030d229a57SStefano Zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2040d229a57SStefano Zampini   PetscValidPointer(vtype, 2);
2050d229a57SStefano Zampini   *vtype = mat->defaultvectype;
2060d229a57SStefano Zampini   PetscFunctionReturn(0);
2070d229a57SStefano Zampini }
2080d229a57SStefano Zampini 
2090d229a57SStefano Zampini /*@C
2100d229a57SStefano Zampini    MatSetVecType - Set the vector type to be used for a matrix object
2110d229a57SStefano Zampini 
2120d229a57SStefano Zampini    Collective on Mat
2130d229a57SStefano Zampini 
2140d229a57SStefano Zampini    Input Parameters:
2150d229a57SStefano Zampini +  mat   - the matrix object
2160d229a57SStefano Zampini -  vtype - vector type
2170d229a57SStefano Zampini 
2180d229a57SStefano Zampini    Notes:
2190d229a57SStefano Zampini      This is rarely needed in practice since each matrix object internally sets the proper vector type.
2200d229a57SStefano Zampini 
2210d229a57SStefano Zampini   Level: intermediate
2220d229a57SStefano Zampini 
223db781477SPatrick Sanan .seealso: `VecSetType()`, `MatGetVecType()`
2240d229a57SStefano Zampini @*/
225*9371c9d4SSatish Balay PetscErrorCode MatSetVecType(Mat mat, VecType vtype) {
2260d229a57SStefano Zampini   PetscFunctionBegin;
2270d229a57SStefano Zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2289566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->defaultvectype));
2299566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(vtype, &mat->defaultvectype));
2300d229a57SStefano Zampini   PetscFunctionReturn(0);
2310d229a57SStefano Zampini }
2327e14e8a7SBarry Smith 
2333cea93caSBarry Smith /*@C
2341c84c290SBarry Smith   MatRegister -  - Adds a new matrix type
2351c84c290SBarry Smith 
2361c84c290SBarry Smith    Not Collective
2371c84c290SBarry Smith 
2381c84c290SBarry Smith    Input Parameters:
2391c84c290SBarry Smith +  name - name of a new user-defined matrix type
2401c84c290SBarry Smith -  routine_create - routine to create method context
2411c84c290SBarry Smith 
2421c84c290SBarry Smith    Notes:
2431c84c290SBarry Smith    MatRegister() may be called multiple times to add several user-defined solvers.
2441c84c290SBarry Smith 
2451c84c290SBarry Smith    Sample usage:
2461c84c290SBarry Smith .vb
247bdf89e91SBarry Smith    MatRegister("my_mat",MyMatCreate);
2481c84c290SBarry Smith .ve
2491c84c290SBarry Smith 
2501c84c290SBarry Smith    Then, your solver can be chosen with the procedural interface via
2511c84c290SBarry Smith $     MatSetType(Mat,"my_mat")
2521c84c290SBarry Smith    or at runtime via the option
2531c84c290SBarry Smith $     -mat_type my_mat
2541c84c290SBarry Smith 
2551c84c290SBarry Smith    Level: advanced
2561c84c290SBarry Smith 
257db781477SPatrick Sanan .seealso: `MatRegisterAll()`
2581c84c290SBarry Smith 
2597f6c08e0SMatthew Knepley   Level: advanced
2603cea93caSBarry Smith @*/
261*9371c9d4SSatish Balay PetscErrorCode MatRegister(const char sname[], PetscErrorCode (*function)(Mat)) {
2627e14e8a7SBarry Smith   PetscFunctionBegin;
2639566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2649566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&MatList, sname, function));
26599cd5145SBarry Smith   PetscFunctionReturn(0);
26699cd5145SBarry Smith }
26799cd5145SBarry Smith 
268f4259b30SLisandro Dalcin MatRootName MatRootNameList = NULL;
26901bebe75SBarry Smith 
27001bebe75SBarry Smith /*@C
27123bebc0bSBarry Smith       MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType()
27223bebc0bSBarry Smith         and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
27323bebc0bSBarry Smith         matrix.
27401bebe75SBarry Smith 
27501bebe75SBarry Smith   Input Parameters:
27623bebc0bSBarry Smith +     rname - the rootname, for example, MATAIJ
27701bebe75SBarry Smith .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
27801bebe75SBarry Smith -     mname - the name of the parallel matrix type, for example, MATMPIAIJ
27901bebe75SBarry Smith 
28023bebc0bSBarry Smith   Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare()
28101bebe75SBarry Smith 
28223bebc0bSBarry Smith   Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the
28323bebc0bSBarry Smith       size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the
28423bebc0bSBarry Smith       appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
28523bebc0bSBarry Smith       confusing.
28623bebc0bSBarry Smith 
28723bebc0bSBarry Smith   Level: developer
28823bebc0bSBarry Smith 
289db781477SPatrick Sanan .seealso: `PetscObjectBaseTypeCompare()`
29023bebc0bSBarry Smith 
29101bebe75SBarry Smith @*/
292*9371c9d4SSatish Balay PetscErrorCode MatRegisterRootName(const char rname[], const char sname[], const char mname[]) {
29323bebc0bSBarry Smith   MatRootName names;
29401bebe75SBarry Smith 
29501bebe75SBarry Smith   PetscFunctionBegin;
2969566063dSJacob Faibussowitsch   PetscCall(PetscNew(&names));
2979566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(rname, &names->rname));
2989566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(sname, &names->sname));
2999566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(mname, &names->mname));
30023bebc0bSBarry Smith   if (!MatRootNameList) {
30123bebc0bSBarry Smith     MatRootNameList = names;
30201bebe75SBarry Smith   } else {
30323bebc0bSBarry Smith     MatRootName next = MatRootNameList;
30401bebe75SBarry Smith     while (next->next) next = next->next;
30501bebe75SBarry Smith     next->next = names;
30601bebe75SBarry Smith   }
30701bebe75SBarry Smith   PetscFunctionReturn(0);
30801bebe75SBarry Smith }
309