xref: /petsc/src/mat/interface/matreg.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRootType_Private(Mat mat, MatType *rootType)
29*d71ae5a4SJacob Faibussowitsch {
302c99ec25SJunchao Zhang   PetscBool   found = PETSC_FALSE;
312c99ec25SJunchao Zhang   MatRootName names = MatRootNameList;
322c99ec25SJunchao Zhang   MatType     inType;
332c99ec25SJunchao Zhang 
342c99ec25SJunchao Zhang   PetscFunctionBegin;
352c99ec25SJunchao Zhang   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
369566063dSJacob Faibussowitsch   PetscCall(MatGetType(mat, &inType));
372c99ec25SJunchao Zhang   while (names) {
389566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(inType, names->mname, &found));
399566063dSJacob Faibussowitsch     if (!found) PetscCall(PetscStrcmp(inType, names->sname, &found));
402c99ec25SJunchao Zhang     if (found) {
412c99ec25SJunchao Zhang       found     = PETSC_TRUE;
422c99ec25SJunchao Zhang       *rootType = names->rname;
432c99ec25SJunchao Zhang       break;
442c99ec25SJunchao Zhang     }
452c99ec25SJunchao Zhang     names = names->next;
462c99ec25SJunchao Zhang   }
472c99ec25SJunchao Zhang   if (!found) *rootType = inType;
482c99ec25SJunchao Zhang   PetscFunctionReturn(0);
492c99ec25SJunchao Zhang }
502c99ec25SJunchao Zhang 
51ac81f253SRichard Tran Mills /* MatGetMPIMatType_Private - Gets the MPI type corresponding to the input matrix's type (e.g., MATMPIAIJ for MATSEQAIJ)
52ac81f253SRichard Tran Mills 
53ac81f253SRichard Tran Mills    Not Collective
54ac81f253SRichard Tran Mills 
55ac81f253SRichard Tran Mills    Input Parameters:
56ac81f253SRichard Tran Mills .  mat      - the input matrix, could be sequential or MPI
57ac81f253SRichard Tran Mills 
58ac81f253SRichard Tran Mills    Output Parameters:
59ac81f253SRichard Tran Mills .  MPIType  - the parallel (MPI) matrix type
60ac81f253SRichard Tran Mills 
61ac81f253SRichard Tran Mills    Level: developer
62ac81f253SRichard Tran Mills 
63ac81f253SRichard Tran Mills .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat`
64ac81f253SRichard Tran Mills */
65*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetMPIMatType_Private(Mat mat, MatType *MPIType)
66*d71ae5a4SJacob Faibussowitsch {
67ac81f253SRichard Tran Mills   PetscBool   found = PETSC_FALSE;
68ac81f253SRichard Tran Mills   MatRootName names = MatRootNameList;
69ac81f253SRichard Tran Mills   MatType     inType;
70ac81f253SRichard Tran Mills 
71ac81f253SRichard Tran Mills   PetscFunctionBegin;
72ac81f253SRichard Tran Mills   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
73ac81f253SRichard Tran Mills   PetscCall(MatGetType(mat, &inType));
74ac81f253SRichard Tran Mills   while (names) {
75ac81f253SRichard Tran Mills     PetscCall(PetscStrcmp(inType, names->sname, &found));
76ac81f253SRichard Tran Mills     if (!found) PetscCall(PetscStrcmp(inType, names->mname, &found));
77ac81f253SRichard Tran Mills     if (!found) PetscCall(PetscStrcmp(inType, names->rname, &found));
78ac81f253SRichard Tran Mills     if (found) {
79ac81f253SRichard Tran Mills       found    = PETSC_TRUE;
80ac81f253SRichard Tran Mills       *MPIType = names->mname;
81ac81f253SRichard Tran Mills       break;
82ac81f253SRichard Tran Mills     }
83ac81f253SRichard Tran Mills     names = names->next;
84ac81f253SRichard Tran Mills   }
85ac81f253SRichard Tran Mills   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_SUP, "No corresponding parallel (MPI) type for this matrix");
86ac81f253SRichard Tran Mills   PetscFunctionReturn(0);
87ac81f253SRichard Tran Mills }
88ac81f253SRichard Tran Mills 
897e14e8a7SBarry Smith /*@C
9099cd5145SBarry Smith    MatSetType - Builds matrix object for a particular matrix type
917e14e8a7SBarry Smith 
9211a5261eSBarry Smith    Collective on mat
937e14e8a7SBarry Smith 
947e14e8a7SBarry Smith    Input Parameters:
9599cd5145SBarry Smith +  mat      - the matrix object
9699cd5145SBarry Smith -  matype   - matrix type
977e14e8a7SBarry Smith 
987e14e8a7SBarry Smith    Options Database Key:
9999cd5145SBarry Smith .  -mat_type  <method> - Sets the type; use -help for a list
10099cd5145SBarry Smith     of available methods (for instance, seqaij)
1017e14e8a7SBarry Smith 
10211a5261eSBarry Smith    Note:
10399cd5145SBarry Smith    See "${PETSC_DIR}/include/petscmat.h" for available methods
1047e14e8a7SBarry Smith 
1057e14e8a7SBarry Smith   Level: intermediate
1067e14e8a7SBarry Smith 
107db781477SPatrick Sanan .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat`
1087e14e8a7SBarry Smith @*/
109*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetType(Mat mat, MatType matype)
110*d71ae5a4SJacob Faibussowitsch {
1113dcd2dd8SBarry Smith   PetscBool   sametype, found, subclass = PETSC_FALSE;
11223bebc0bSBarry Smith   MatRootName names = MatRootNameList;
1135f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Mat);
1147e14e8a7SBarry Smith 
1157e14e8a7SBarry Smith   PetscFunctionBegin;
1160700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
117117016b1SBarry Smith 
11801bebe75SBarry Smith   while (names) {
1199566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(matype, names->rname, &found));
12001bebe75SBarry Smith     if (found) {
12101bebe75SBarry Smith       PetscMPIInt size;
1229566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
12301bebe75SBarry Smith       if (size == 1) matype = names->sname;
12401bebe75SBarry Smith       else matype = names->mname;
12501bebe75SBarry Smith       break;
12601bebe75SBarry Smith     }
12701bebe75SBarry Smith     names = names->next;
12801bebe75SBarry Smith   }
12901bebe75SBarry Smith 
1309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype));
13192ff6ae8SBarry Smith   if (sametype) PetscFunctionReturn(0);
13292ff6ae8SBarry Smith 
1339566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(MatList, matype, &r));
1345f80ce2aSJacob Faibussowitsch   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype);
1357e14e8a7SBarry Smith 
1369566063dSJacob Faibussowitsch   if (mat->assembled && ((PetscObject)mat)->type_name) PetscCall(PetscStrbeginswith(matype, ((PetscObject)mat)->type_name, &subclass));
1373dcd2dd8SBarry Smith   if (subclass) {
1389566063dSJacob Faibussowitsch     PetscCall(MatConvert(mat, matype, MAT_INPLACE_MATRIX, &mat));
1393dcd2dd8SBarry Smith     PetscFunctionReturn(0);
14028fc0bbcSJose E. Roman   }
141dbbe0bcdSBarry Smith   PetscTryTypeMethod(mat, destroy);
1420298fd71SBarry Smith   mat->ops->destroy = NULL;
14382e0f345SBarry Smith 
14432e7c8b0SBarry Smith   /* should these null spaces be removed? */
1459566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
1469566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
147dbbe0bcdSBarry Smith 
1489566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(mat->ops, sizeof(struct _MatOps)));
14982e0f345SBarry Smith   mat->preallocated  = PETSC_FALSE;
15082e0f345SBarry Smith   mat->assembled     = PETSC_FALSE;
15182e0f345SBarry Smith   mat->was_assembled = PETSC_FALSE;
15282e0f345SBarry Smith 
15382e0f345SBarry Smith   /*
15482e0f345SBarry Smith    Increment, rather than reset these: the object is logically the same, so its logging and
15582e0f345SBarry Smith    state is inherited.  Furthermore, resetting makes it possible for the same state to be
15682e0f345SBarry Smith    obtained with a different structure, confusing the PC.
15782e0f345SBarry Smith   */
15832e7c8b0SBarry Smith   mat->nonzerostate++;
1599566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
160a2ec6df8SKris Buschelman 
16135d8aa7fSBarry Smith   /* create the new data structure */
1629566063dSJacob Faibussowitsch   PetscCall((*r)(mat));
1637e14e8a7SBarry Smith   PetscFunctionReturn(0);
1647e14e8a7SBarry Smith }
1657e14e8a7SBarry Smith 
1667e14e8a7SBarry Smith /*@C
167f87b78b8SBarry Smith    MatGetType - Gets the matrix type as a string from the matrix object.
1687e14e8a7SBarry Smith 
1697e14e8a7SBarry Smith    Not Collective
1707e14e8a7SBarry Smith 
1717e14e8a7SBarry Smith    Input Parameter:
17299cd5145SBarry Smith .  mat - the matrix
1737e14e8a7SBarry Smith 
1747e14e8a7SBarry Smith    Output Parameter:
17599cd5145SBarry Smith .  name - name of matrix type
1767e14e8a7SBarry Smith 
1777e14e8a7SBarry Smith    Level: intermediate
1787e14e8a7SBarry Smith 
17911a5261eSBarry Smith .seealso: `MatType`, `MatSetType()`
1807e14e8a7SBarry Smith @*/
181*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetType(Mat mat, MatType *type)
182*d71ae5a4SJacob Faibussowitsch {
1837e14e8a7SBarry Smith   PetscFunctionBegin;
1840700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
185c4e43342SLisandro Dalcin   PetscValidPointer(type, 2);
1867adad957SLisandro Dalcin   *type = ((PetscObject)mat)->type_name;
1877e14e8a7SBarry Smith   PetscFunctionReturn(0);
1887e14e8a7SBarry Smith }
1897e14e8a7SBarry Smith 
1900d229a57SStefano Zampini /*@C
19111a5261eSBarry Smith    MatGetVecType - Gets the vector type the matrix will return with `MatCreateVecs()`
1920d229a57SStefano Zampini 
1930d229a57SStefano Zampini    Not Collective
1940d229a57SStefano Zampini 
1950d229a57SStefano Zampini    Input Parameter:
1960d229a57SStefano Zampini .  mat - the matrix
1970d229a57SStefano Zampini 
1980d229a57SStefano Zampini    Output Parameter:
1990d229a57SStefano Zampini .  name - name of vector type
2000d229a57SStefano Zampini 
2010d229a57SStefano Zampini    Level: intermediate
2020d229a57SStefano Zampini 
20311a5261eSBarry Smith .seealso: `MatType`, `Mat`, `MatSetVecType()`, `VecType`
2040d229a57SStefano Zampini @*/
205*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetVecType(Mat mat, VecType *vtype)
206*d71ae5a4SJacob Faibussowitsch {
2070d229a57SStefano Zampini   PetscFunctionBegin;
2080d229a57SStefano Zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2090d229a57SStefano Zampini   PetscValidPointer(vtype, 2);
2100d229a57SStefano Zampini   *vtype = mat->defaultvectype;
2110d229a57SStefano Zampini   PetscFunctionReturn(0);
2120d229a57SStefano Zampini }
2130d229a57SStefano Zampini 
2140d229a57SStefano Zampini /*@C
21511a5261eSBarry Smith    MatSetVecType - Set the vector type the matrix will return with `MatCreateVecs()`
2160d229a57SStefano Zampini 
21711a5261eSBarry Smith    Collective on mat
2180d229a57SStefano Zampini 
2190d229a57SStefano Zampini    Input Parameters:
2200d229a57SStefano Zampini +  mat   - the matrix object
2210d229a57SStefano Zampini -  vtype - vector type
2220d229a57SStefano Zampini 
22311a5261eSBarry Smith    Note:
2240d229a57SStefano Zampini      This is rarely needed in practice since each matrix object internally sets the proper vector type.
2250d229a57SStefano Zampini 
2260d229a57SStefano Zampini   Level: intermediate
2270d229a57SStefano Zampini 
22811a5261eSBarry Smith .seealso: `VecType`, `VecSetType()`, `MatGetVecType()`
2290d229a57SStefano Zampini @*/
230*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetVecType(Mat mat, VecType vtype)
231*d71ae5a4SJacob Faibussowitsch {
2320d229a57SStefano Zampini   PetscFunctionBegin;
2330d229a57SStefano Zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2349566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->defaultvectype));
2359566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(vtype, &mat->defaultvectype));
2360d229a57SStefano Zampini   PetscFunctionReturn(0);
2370d229a57SStefano Zampini }
2387e14e8a7SBarry Smith 
2393cea93caSBarry Smith /*@C
2401c84c290SBarry Smith   MatRegister -  - Adds a new matrix type
2411c84c290SBarry Smith 
2421c84c290SBarry Smith    Not Collective
2431c84c290SBarry Smith 
2441c84c290SBarry Smith    Input Parameters:
2451c84c290SBarry Smith +  name - name of a new user-defined matrix type
2461c84c290SBarry Smith -  routine_create - routine to create method context
2471c84c290SBarry Smith 
24811a5261eSBarry Smith    Note:
24911a5261eSBarry Smith    `MatRegister()` may be called multiple times to add several user-defined solvers.
2501c84c290SBarry Smith 
2511c84c290SBarry Smith    Sample usage:
2521c84c290SBarry Smith .vb
253bdf89e91SBarry Smith    MatRegister("my_mat",MyMatCreate);
2541c84c290SBarry Smith .ve
2551c84c290SBarry Smith 
2561c84c290SBarry Smith    Then, your solver can be chosen with the procedural interface via
2571c84c290SBarry Smith $     MatSetType(Mat,"my_mat")
2581c84c290SBarry Smith    or at runtime via the option
2591c84c290SBarry Smith $     -mat_type my_mat
2601c84c290SBarry Smith 
2611c84c290SBarry Smith    Level: advanced
2621c84c290SBarry Smith 
26311a5261eSBarry Smith .seealso: `Mat`, `MatType`, `MatSetType()`, `MatRegisterAll()`
2643cea93caSBarry Smith @*/
265*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRegister(const char sname[], PetscErrorCode (*function)(Mat))
266*d71ae5a4SJacob Faibussowitsch {
2677e14e8a7SBarry Smith   PetscFunctionBegin;
2689566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2699566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&MatList, sname, function));
27099cd5145SBarry Smith   PetscFunctionReturn(0);
27199cd5145SBarry Smith }
27299cd5145SBarry Smith 
273f4259b30SLisandro Dalcin MatRootName MatRootNameList = NULL;
27401bebe75SBarry Smith 
27501bebe75SBarry Smith /*@C
27611a5261eSBarry Smith       MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. `MatSetType()`
27723bebc0bSBarry Smith         and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
27823bebc0bSBarry Smith         matrix.
27901bebe75SBarry Smith 
28001bebe75SBarry Smith   Input Parameters:
28111a5261eSBarry Smith +     rname - the rootname, for example, `MATAIJ`
28211a5261eSBarry Smith .     sname - the name of the sequential matrix type, for example, `MATSEQAIJ`
28311a5261eSBarry Smith -     mname - the name of the parallel matrix type, for example, `MATMPIAIJ`
28401bebe75SBarry Smith 
28511a5261eSBarry Smith   Note:
28611a5261eSBarry Smith   The matrix rootname should not be confused with the base type of the function `PetscObjectBaseTypeCompare()`
28701bebe75SBarry Smith 
28811a5261eSBarry Smith   Developer Note:
28911a5261eSBarry Smith   PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate `VecType` based on the
29011a5261eSBarry Smith       size of the communicator but it is implemented by simply having additional `VecCreate_RootName()` registerer routines that dispatch to the
29123bebc0bSBarry Smith       appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
29223bebc0bSBarry Smith       confusing.
29323bebc0bSBarry Smith 
29423bebc0bSBarry Smith   Level: developer
29523bebc0bSBarry Smith 
29611a5261eSBarry Smith .seealso: `Mat`, `MatType`, `PetscObjectBaseTypeCompare()`
29701bebe75SBarry Smith @*/
298*d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRegisterRootName(const char rname[], const char sname[], const char mname[])
299*d71ae5a4SJacob Faibussowitsch {
30023bebc0bSBarry Smith   MatRootName names;
30101bebe75SBarry Smith 
30201bebe75SBarry Smith   PetscFunctionBegin;
3039566063dSJacob Faibussowitsch   PetscCall(PetscNew(&names));
3049566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(rname, &names->rname));
3059566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(sname, &names->sname));
3069566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(mname, &names->mname));
30723bebc0bSBarry Smith   if (!MatRootNameList) {
30823bebc0bSBarry Smith     MatRootNameList = names;
30901bebe75SBarry Smith   } else {
31023bebc0bSBarry Smith     MatRootName next = MatRootNameList;
31101bebe75SBarry Smith     while (next->next) next = next->next;
31201bebe75SBarry Smith     next->next = names;
31301bebe75SBarry Smith   }
31401bebe75SBarry Smith   PetscFunctionReturn(0);
31501bebe75SBarry Smith }
316