xref: /petsc/src/mat/interface/matreg.c (revision 76d6960897ba55d8238485170da43545084300c6)
17e14e8a7SBarry Smith /*
299cd5145SBarry Smith      Mechanism for register PETSc matrix types
37e14e8a7SBarry Smith */
4af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
57e14e8a7SBarry Smith 
6ace3abfcSBarry Smith PetscBool MatRegisterAllCalled = PETSC_FALSE;
77e14e8a7SBarry Smith 
87e14e8a7SBarry Smith /*
999cd5145SBarry Smith    Contains the list of registered Mat routines
107e14e8a7SBarry Smith */
11f4259b30SLisandro Dalcin PetscFunctionList MatList = NULL;
127e14e8a7SBarry Smith 
132c99ec25SJunchao Zhang /* MatGetRootType_Private - Gets the root type of the input matrix's type (e.g., MATAIJ for MATSEQAIJ)
142c99ec25SJunchao Zhang 
152c99ec25SJunchao Zhang    Not Collective
162c99ec25SJunchao Zhang 
172fe279fdSBarry Smith    Input Parameter:
182c99ec25SJunchao Zhang .  mat      - the input matrix, could be sequential or MPI
192c99ec25SJunchao Zhang 
202fe279fdSBarry Smith    Output Parameter:
212c99ec25SJunchao Zhang .  rootType  - the root matrix type
222c99ec25SJunchao Zhang 
232c99ec25SJunchao Zhang    Level: developer
242c99ec25SJunchao Zhang 
25db781477SPatrick Sanan .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat`
262c99ec25SJunchao Zhang */
MatGetRootType_Private(Mat mat,MatType * rootType)27d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetRootType_Private(Mat mat, MatType *rootType)
28d71ae5a4SJacob Faibussowitsch {
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;
473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
542fe279fdSBarry Smith    Input Parameter:
55ac81f253SRichard Tran Mills .  mat      - the input matrix, could be sequential or MPI
56ac81f253SRichard Tran Mills 
572fe279fdSBarry Smith    Output Parameter:
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 */
MatGetMPIMatType_Private(Mat mat,MatType * MPIType)64d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetMPIMatType_Private(Mat mat, MatType *MPIType)
65d71ae5a4SJacob Faibussowitsch {
66ac81f253SRichard Tran Mills   PetscBool   found = PETSC_FALSE;
67ac81f253SRichard Tran Mills   MatRootName names = MatRootNameList;
68ac81f253SRichard Tran Mills   MatType     inType;
69ac81f253SRichard Tran Mills 
70ac81f253SRichard Tran Mills   PetscFunctionBegin;
71ac81f253SRichard Tran Mills   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
72ac81f253SRichard Tran Mills   PetscCall(MatGetType(mat, &inType));
73ac81f253SRichard Tran Mills   while (names) {
74ac81f253SRichard Tran Mills     PetscCall(PetscStrcmp(inType, names->sname, &found));
75ac81f253SRichard Tran Mills     if (!found) PetscCall(PetscStrcmp(inType, names->mname, &found));
76ac81f253SRichard Tran Mills     if (!found) PetscCall(PetscStrcmp(inType, names->rname, &found));
77ac81f253SRichard Tran Mills     if (found) {
78ac81f253SRichard Tran Mills       found    = PETSC_TRUE;
79ac81f253SRichard Tran Mills       *MPIType = names->mname;
80ac81f253SRichard Tran Mills       break;
81ac81f253SRichard Tran Mills     }
82ac81f253SRichard Tran Mills     names = names->next;
83ac81f253SRichard Tran Mills   }
84ac81f253SRichard Tran Mills   PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_SUP, "No corresponding parallel (MPI) type for this matrix");
853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86ac81f253SRichard Tran Mills }
87ac81f253SRichard Tran Mills 
88cc4c1da9SBarry Smith /*@
8999cd5145SBarry Smith   MatSetType - Builds matrix object for a particular matrix type
907e14e8a7SBarry Smith 
91c3339decSBarry Smith   Collective
927e14e8a7SBarry Smith 
937e14e8a7SBarry Smith   Input Parameters:
9499cd5145SBarry Smith + mat    - the matrix object
9599cd5145SBarry Smith - matype - matrix type
967e14e8a7SBarry Smith 
977e14e8a7SBarry Smith   Options Database Key:
982ef1f0ffSBarry Smith . -mat_type  <method> - Sets the type; see `MatType`
997e14e8a7SBarry Smith 
1007e14e8a7SBarry Smith   Level: intermediate
1017e14e8a7SBarry Smith 
1022ef1f0ffSBarry Smith   Note:
1032ef1f0ffSBarry Smith   See `MatType` for possible values
1042ef1f0ffSBarry Smith 
105fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`
1067e14e8a7SBarry Smith @*/
MatSetType(Mat mat,MatType matype)107d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetType(Mat mat, MatType matype)
108d71ae5a4SJacob Faibussowitsch {
109a0bcfa1fSJunchao Zhang   PetscBool   sametype, found, subclass = PETSC_FALSE, matMPI = PETSC_FALSE, requestSeq = PETSC_FALSE;
11023bebc0bSBarry Smith   MatRootName names = MatRootNameList;
1115f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Mat);
1127e14e8a7SBarry Smith 
1137e14e8a7SBarry Smith   PetscFunctionBegin;
1140700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
115117016b1SBarry Smith 
1169f3dd13dSJunchao Zhang   /* make this special case fast */
1179f3dd13dSJunchao Zhang   PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype));
1183ba16761SJacob Faibussowitsch   if (sametype) PetscFunctionReturn(PETSC_SUCCESS);
1199f3dd13dSJunchao Zhang 
120a0bcfa1fSJunchao Zhang   /* suppose with one MPI process, one created an MPIAIJ (mpiaij) matrix with MatCreateMPIAIJWithArrays(), and later tried
121a0bcfa1fSJunchao Zhang      to change its type via '-mat_type aijcusparse'. Even there is only one MPI rank, we need to adapt matype to
122a0bcfa1fSJunchao Zhang      'mpiaijcusparse' so that it will be treated as a subclass of MPIAIJ and proper MatCovert() will be called.
123a0bcfa1fSJunchao Zhang   */
124a0bcfa1fSJunchao Zhang   if (((PetscObject)mat)->type_name) PetscCall(PetscStrbeginswith(((PetscObject)mat)->type_name, "mpi", &matMPI)); /* mat claims itself is an 'mpi' matrix */
125a0bcfa1fSJunchao Zhang   if (matype) PetscCall(PetscStrbeginswith(matype, "seq", &requestSeq));                                           /* user is requesting a 'seq' matrix */
126a0bcfa1fSJunchao Zhang   PetscCheck(!(matMPI && requestSeq), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Changing an MPI matrix (%s) to a sequential one (%s) is not allowed. Please remove the 'seq' prefix from your matrix type.", ((PetscObject)mat)->type_name, matype);
127a0bcfa1fSJunchao Zhang 
12801bebe75SBarry Smith   while (names) {
1299566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(matype, names->rname, &found));
13001bebe75SBarry Smith     if (found) {
13101bebe75SBarry Smith       PetscMPIInt size;
1329566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
133a0bcfa1fSJunchao Zhang       if (size == 1 && !matMPI) matype = names->sname; /* try to align the requested type (matype) with the existing type per seq/mpi */
13401bebe75SBarry Smith       else matype = names->mname;
13501bebe75SBarry Smith       break;
13601bebe75SBarry Smith     }
13701bebe75SBarry Smith     names = names->next;
13801bebe75SBarry Smith   }
13901bebe75SBarry Smith 
1409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)mat, matype, &sametype));
1413ba16761SJacob Faibussowitsch   if (sametype) PetscFunctionReturn(PETSC_SUCCESS);
14292ff6ae8SBarry Smith 
1439566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(MatList, matype, &r));
1446adde796SStefano Zampini   PetscCheck(r, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Mat type given: %s", matype);
1457e14e8a7SBarry Smith 
1469566063dSJacob Faibussowitsch   if (mat->assembled && ((PetscObject)mat)->type_name) PetscCall(PetscStrbeginswith(matype, ((PetscObject)mat)->type_name, &subclass));
147a0bcfa1fSJunchao Zhang   if (subclass) { /* mat is a subclass of the requested 'matype'? */
1489566063dSJacob Faibussowitsch     PetscCall(MatConvert(mat, matype, MAT_INPLACE_MATRIX, &mat));
1493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
15028fc0bbcSJose E. Roman   }
151b79e0553SHong Zhang   if (names && mat->assembled) {
152b79e0553SHong Zhang     PetscCall(PetscStrbeginswith(names->rname, "sell", &sametype));
153b79e0553SHong Zhang     if (sametype) {                                                  /* mattype is MATSELL or its subclass */
154b79e0553SHong Zhang       PetscCall(MatConvert(mat, MATSELL, MAT_INPLACE_MATRIX, &mat)); /* convert to matsell first */
155b79e0553SHong Zhang       PetscCall(MatConvert(mat, matype, MAT_INPLACE_MATRIX, &mat));
156b79e0553SHong Zhang       PetscFunctionReturn(PETSC_SUCCESS);
157b79e0553SHong Zhang     }
158b79e0553SHong Zhang   }
159dbbe0bcdSBarry Smith   PetscTryTypeMethod(mat, destroy);
1600298fd71SBarry Smith   mat->ops->destroy = NULL;
16182e0f345SBarry Smith 
16232e7c8b0SBarry Smith   /* should these null spaces be removed? */
1639566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
1649566063dSJacob Faibussowitsch   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
165dbbe0bcdSBarry Smith 
1669566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(mat->ops, sizeof(struct _MatOps)));
16782e0f345SBarry Smith   mat->preallocated  = PETSC_FALSE;
16882e0f345SBarry Smith   mat->assembled     = PETSC_FALSE;
16982e0f345SBarry Smith   mat->was_assembled = PETSC_FALSE;
17082e0f345SBarry Smith 
17182e0f345SBarry Smith   /*
17282e0f345SBarry Smith    Increment, rather than reset these: the object is logically the same, so its logging and
17382e0f345SBarry Smith    state is inherited.  Furthermore, resetting makes it possible for the same state to be
17482e0f345SBarry Smith    obtained with a different structure, confusing the PC.
17582e0f345SBarry Smith   */
17632e7c8b0SBarry Smith   mat->nonzerostate++;
1779566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
178a2ec6df8SKris Buschelman 
17935d8aa7fSBarry Smith   /* create the new data structure */
1809566063dSJacob Faibussowitsch   PetscCall((*r)(mat));
1813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1827e14e8a7SBarry Smith }
1837e14e8a7SBarry Smith 
184cc4c1da9SBarry Smith /*@
185f87b78b8SBarry Smith   MatGetType - Gets the matrix type as a string from the matrix object.
1867e14e8a7SBarry Smith 
1877e14e8a7SBarry Smith   Not Collective
1887e14e8a7SBarry Smith 
1897e14e8a7SBarry Smith   Input Parameter:
19099cd5145SBarry Smith . mat - the matrix
1917e14e8a7SBarry Smith 
1927e14e8a7SBarry Smith   Output Parameter:
193fe59aa6dSJacob Faibussowitsch . type - name of matrix type
1947e14e8a7SBarry Smith 
1957e14e8a7SBarry Smith   Level: intermediate
1967e14e8a7SBarry Smith 
1971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatType`, `MatSetType()`
1987e14e8a7SBarry Smith @*/
MatGetType(Mat mat,MatType * type)199d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetType(Mat mat, MatType *type)
200d71ae5a4SJacob Faibussowitsch {
2017e14e8a7SBarry Smith   PetscFunctionBegin;
2020700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2034f572ea9SToby Isaac   PetscAssertPointer(type, 2);
2047adad957SLisandro Dalcin   *type = ((PetscObject)mat)->type_name;
2053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2067e14e8a7SBarry Smith }
2077e14e8a7SBarry Smith 
208963a61daSJose E. Roman /*@
20911a5261eSBarry Smith   MatGetVecType - Gets the vector type the matrix will return with `MatCreateVecs()`
2100d229a57SStefano Zampini 
2110d229a57SStefano Zampini   Not Collective
2120d229a57SStefano Zampini 
2130d229a57SStefano Zampini   Input Parameter:
2140d229a57SStefano Zampini . mat - the matrix
2150d229a57SStefano Zampini 
2160d229a57SStefano Zampini   Output Parameter:
217fe59aa6dSJacob Faibussowitsch . vtype - name of vector type
2180d229a57SStefano Zampini 
2190d229a57SStefano Zampini   Level: intermediate
2200d229a57SStefano Zampini 
221fe59aa6dSJacob Faibussowitsch .seealso: [](ch_matrices), `Mat`, `MatType`, `MatSetVecType()`, `VecType`
2220d229a57SStefano Zampini @*/
MatGetVecType(Mat mat,VecType * vtype)223d71ae5a4SJacob Faibussowitsch PetscErrorCode MatGetVecType(Mat mat, VecType *vtype)
224d71ae5a4SJacob Faibussowitsch {
2250d229a57SStefano Zampini   PetscFunctionBegin;
2260d229a57SStefano Zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2274f572ea9SToby Isaac   PetscAssertPointer(vtype, 2);
2280d229a57SStefano Zampini   *vtype = mat->defaultvectype;
2293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2300d229a57SStefano Zampini }
2310d229a57SStefano Zampini 
232963a61daSJose E. Roman /*@
23311a5261eSBarry Smith   MatSetVecType - Set the vector type the matrix will return with `MatCreateVecs()`
2340d229a57SStefano Zampini 
235c3339decSBarry Smith   Collective
2360d229a57SStefano Zampini 
2370d229a57SStefano Zampini   Input Parameters:
2380d229a57SStefano Zampini + mat   - the matrix object
2390d229a57SStefano Zampini - vtype - vector type
2400d229a57SStefano Zampini 
2412ef1f0ffSBarry Smith   Level: advanced
2422ef1f0ffSBarry Smith 
24311a5261eSBarry Smith   Note:
2440d229a57SStefano Zampini   This is rarely needed in practice since each matrix object internally sets the proper vector type.
2450d229a57SStefano Zampini 
2461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `VecType`, `VecSetType()`, `MatGetVecType()`
2470d229a57SStefano Zampini @*/
MatSetVecType(Mat mat,VecType vtype)248d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetVecType(Mat mat, VecType vtype)
249d71ae5a4SJacob Faibussowitsch {
2500d229a57SStefano Zampini   PetscFunctionBegin;
2510d229a57SStefano Zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2529566063dSJacob Faibussowitsch   PetscCall(PetscFree(mat->defaultvectype));
2539566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(vtype, &mat->defaultvectype));
2543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2550d229a57SStefano Zampini }
2567e14e8a7SBarry Smith 
2573cea93caSBarry Smith /*@C
258*0b4b7b1cSBarry Smith   MatRegister - Adds a new matrix type implementation that is usable as a `Mat` in PETSc
2591c84c290SBarry Smith 
260cc4c1da9SBarry Smith   Not Collective, No Fortran Support
2611c84c290SBarry Smith 
2621c84c290SBarry Smith   Input Parameters:
26367be906fSBarry Smith + sname    - name of a new user-defined matrix type
26467be906fSBarry Smith - function - routine to create method context
26567be906fSBarry Smith 
26667be906fSBarry Smith   Level: advanced
2671c84c290SBarry Smith 
26811a5261eSBarry Smith   Note:
26911a5261eSBarry Smith   `MatRegister()` may be called multiple times to add several user-defined solvers.
2701c84c290SBarry Smith 
271*0b4b7b1cSBarry Smith   A simpler alternative to using `MatRegister()` for an application specific matrix format is to use `MatCreateShell()`, which
272*0b4b7b1cSBarry Smith   generates a `Mat` of `MatType` `MATSHELL`. One can then use `MatShellSetContext()` and `MatShellSetOperation()` to provide
273*0b4b7b1cSBarry Smith   the data structures and routines customized for their matrix format.
274*0b4b7b1cSBarry Smith 
275fe59aa6dSJacob Faibussowitsch   Example Usage:
2761c84c290SBarry Smith .vb
277bdf89e91SBarry Smith    MatRegister("my_mat", MyMatCreate);
2781c84c290SBarry Smith .ve
2791c84c290SBarry Smith 
280a3b724e8SBarry Smith   Then, your solver can be chosen with the procedural interface via `MatSetType(Mat, "my_mat")` or at runtime via the option
281a3b724e8SBarry Smith   `-mat_type my_mat`
2821c84c290SBarry Smith 
2831cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatType`, `MatSetType()`, `MatRegisterAll()`
2843cea93caSBarry Smith @*/
MatRegister(const char sname[],PetscErrorCode (* function)(Mat))285d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRegister(const char sname[], PetscErrorCode (*function)(Mat))
286d71ae5a4SJacob Faibussowitsch {
2877e14e8a7SBarry Smith   PetscFunctionBegin;
2889566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2899566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&MatList, sname, function));
2903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29199cd5145SBarry Smith }
29299cd5145SBarry Smith 
293f4259b30SLisandro Dalcin MatRootName MatRootNameList = NULL;
29401bebe75SBarry Smith 
295cc4c1da9SBarry Smith /*@
2962920cce0SJacob Faibussowitsch   MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type.
29701bebe75SBarry Smith 
29801bebe75SBarry Smith   Input Parameters:
29911a5261eSBarry Smith + rname - the rootname, for example, `MATAIJ`
30011a5261eSBarry Smith . sname - the name of the sequential matrix type, for example, `MATSEQAIJ`
30111a5261eSBarry Smith - mname - the name of the parallel matrix type, for example, `MATMPIAIJ`
30201bebe75SBarry Smith 
30367be906fSBarry Smith   Level: developer
30467be906fSBarry Smith 
3052920cce0SJacob Faibussowitsch   Notes:
3062920cce0SJacob Faibussowitsch   `MatSetType()` and `-mat_type name` will automatically use the sequential or parallel version
3072920cce0SJacob Faibussowitsch   based on the size of the MPI communicator associated with the matrix.
3082920cce0SJacob Faibussowitsch 
3092920cce0SJacob Faibussowitsch   The matrix rootname should not be confused with the base type of the function
3102920cce0SJacob Faibussowitsch   `PetscObjectBaseTypeCompare()`
31101bebe75SBarry Smith 
312fe59aa6dSJacob Faibussowitsch   Developer Notes:
31311a5261eSBarry Smith   PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate `VecType` based on the
31411a5261eSBarry Smith   size of the communicator but it is implemented by simply having additional `VecCreate_RootName()` registerer routines that dispatch to the
31523bebc0bSBarry Smith   appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
31623bebc0bSBarry Smith   confusing.
31723bebc0bSBarry Smith 
3181cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatType`, `PetscObjectBaseTypeCompare()`
31901bebe75SBarry Smith @*/
MatRegisterRootName(const char rname[],const char sname[],const char mname[])320d71ae5a4SJacob Faibussowitsch PetscErrorCode MatRegisterRootName(const char rname[], const char sname[], const char mname[])
321d71ae5a4SJacob Faibussowitsch {
32223bebc0bSBarry Smith   MatRootName names;
32301bebe75SBarry Smith 
32401bebe75SBarry Smith   PetscFunctionBegin;
3259566063dSJacob Faibussowitsch   PetscCall(PetscNew(&names));
3269566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(rname, &names->rname));
3279566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(sname, &names->sname));
3289566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(mname, &names->mname));
32923bebc0bSBarry Smith   if (!MatRootNameList) {
33023bebc0bSBarry Smith     MatRootNameList = names;
33101bebe75SBarry Smith   } else {
33223bebc0bSBarry Smith     MatRootName next = MatRootNameList;
33301bebe75SBarry Smith     while (next->next) next = next->next;
33401bebe75SBarry Smith     next->next = names;
33501bebe75SBarry Smith   }
3363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33701bebe75SBarry Smith }
338