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