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: /* MatGetMPIMatType_Private - Gets the MPI type corresponding to the input matrix's type (e.g., MATMPIAIJ for MATSEQAIJ)

 52:    Not Collective

 54:    Input Parameters:
 55: .  mat      - the input matrix, could be sequential or MPI

 57:    Output Parameters:
 58: .  MPIType  - the parallel (MPI) matrix type

 60:    Level: developer

 62: .seealso: `MatGetType()`, `MatSetType()`, `MatType`, `Mat`
 63: */
 64: PetscErrorCode MatGetMPIMatType_Private(Mat mat, MatType *MPIType)
 65: {
 66:   PetscBool   found = PETSC_FALSE;
 67:   MatRootName names = MatRootNameList;
 68:   MatType     inType;

 71:   MatGetType(mat, &inType);
 72:   while (names) {
 73:     PetscStrcmp(inType, names->sname, &found);
 74:     if (!found) PetscStrcmp(inType, names->mname, &found);
 75:     if (!found) PetscStrcmp(inType, names->rname, &found);
 76:     if (found) {
 77:       found    = PETSC_TRUE;
 78:       *MPIType = names->mname;
 79:       break;
 80:     }
 81:     names = names->next;
 82:   }
 84:   return 0;
 85: }

 87: /*@C
 88:    MatSetType - Builds matrix object for a particular matrix type

 90:    Collective on mat

 92:    Input Parameters:
 93: +  mat      - the matrix object
 94: -  matype   - matrix type

 96:    Options Database Key:
 97: .  -mat_type  <method> - Sets the type; use -help for a list
 98:     of available methods (for instance, seqaij)

100:    Note:
101:    See "${PETSC_DIR}/include/petscmat.h" for available methods

103:   Level: intermediate

105: .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat`
106: @*/
107: PetscErrorCode MatSetType(Mat mat, MatType matype)
108: {
109:   PetscBool   sametype, found, subclass = PETSC_FALSE;
110:   MatRootName names = MatRootNameList;
111:   PetscErrorCode (*r)(Mat);


115:   while (names) {
116:     PetscStrcmp(matype, names->rname, &found);
117:     if (found) {
118:       PetscMPIInt size;
119:       MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size);
120:       if (size == 1) matype = names->sname;
121:       else matype = names->mname;
122:       break;
123:     }
124:     names = names->next;
125:   }

127:   PetscObjectTypeCompare((PetscObject)mat, matype, &sametype);
128:   if (sametype) return 0;

130:   PetscFunctionListFind(MatList, matype, &r);

133:   if (mat->assembled && ((PetscObject)mat)->type_name) PetscStrbeginswith(matype, ((PetscObject)mat)->type_name, &subclass);
134:   if (subclass) {
135:     MatConvert(mat, matype, MAT_INPLACE_MATRIX, &mat);
136:     return 0;
137:   }
138:   PetscTryTypeMethod(mat, destroy);
139:   mat->ops->destroy = NULL;

141:   /* should these null spaces be removed? */
142:   MatNullSpaceDestroy(&mat->nullsp);
143:   MatNullSpaceDestroy(&mat->nearnullsp);

145:   PetscMemzero(mat->ops, sizeof(struct _MatOps));
146:   mat->preallocated  = PETSC_FALSE;
147:   mat->assembled     = PETSC_FALSE;
148:   mat->was_assembled = PETSC_FALSE;

150:   /*
151:    Increment, rather than reset these: the object is logically the same, so its logging and
152:    state is inherited.  Furthermore, resetting makes it possible for the same state to be
153:    obtained with a different structure, confusing the PC.
154:   */
155:   mat->nonzerostate++;
156:   PetscObjectStateIncrease((PetscObject)mat);

158:   /* create the new data structure */
159:   (*r)(mat);
160:   return 0;
161: }

163: /*@C
164:    MatGetType - Gets the matrix type as a string from the matrix object.

166:    Not Collective

168:    Input Parameter:
169: .  mat - the matrix

171:    Output Parameter:
172: .  name - name of matrix type

174:    Level: intermediate

176: .seealso: `MatType`, `MatSetType()`
177: @*/
178: PetscErrorCode MatGetType(Mat mat, MatType *type)
179: {
182:   *type = ((PetscObject)mat)->type_name;
183:   return 0;
184: }

186: /*@C
187:    MatGetVecType - Gets the vector type the matrix will return with `MatCreateVecs()`

189:    Not Collective

191:    Input Parameter:
192: .  mat - the matrix

194:    Output Parameter:
195: .  name - name of vector type

197:    Level: intermediate

199: .seealso: `MatType`, `Mat`, `MatSetVecType()`, `VecType`
200: @*/
201: PetscErrorCode MatGetVecType(Mat mat, VecType *vtype)
202: {
205:   *vtype = mat->defaultvectype;
206:   return 0;
207: }

209: /*@C
210:    MatSetVecType - Set the vector type the matrix will return with `MatCreateVecs()`

212:    Collective on mat

214:    Input Parameters:
215: +  mat   - the matrix object
216: -  vtype - vector type

218:    Note:
219:      This is rarely needed in practice since each matrix object internally sets the proper vector type.

221:   Level: intermediate

223: .seealso: `VecType`, `VecSetType()`, `MatGetVecType()`
224: @*/
225: PetscErrorCode MatSetVecType(Mat mat, VecType vtype)
226: {
228:   PetscFree(mat->defaultvectype);
229:   PetscStrallocpy(vtype, &mat->defaultvectype);
230:   return 0;
231: }

233: /*@C
234:   MatRegister -  - Adds a new matrix type

236:    Not Collective

238:    Input Parameters:
239: +  name - name of a new user-defined matrix type
240: -  routine_create - routine to create method context

242:    Note:
243:    `MatRegister()` may be called multiple times to add several user-defined solvers.

245:    Sample usage:
246: .vb
247:    MatRegister("my_mat",MyMatCreate);
248: .ve

250:    Then, your solver can be chosen with the procedural interface via
251: $     MatSetType(Mat,"my_mat")
252:    or at runtime via the option
253: $     -mat_type my_mat

255:    Level: advanced

257: .seealso: `Mat`, `MatType`, `MatSetType()`, `MatRegisterAll()`
258: @*/
259: PetscErrorCode MatRegister(const char sname[], PetscErrorCode (*function)(Mat))
260: {
261:   MatInitializePackage();
262:   PetscFunctionListAdd(&MatList, sname, function);
263:   return 0;
264: }

266: MatRootName MatRootNameList = NULL;

268: /*@C
269:       MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. `MatSetType()`
270:         and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the
271:         matrix.

273:   Input Parameters:
274: +     rname - the rootname, for example, `MATAIJ`
275: .     sname - the name of the sequential matrix type, for example, `MATSEQAIJ`
276: -     mname - the name of the parallel matrix type, for example, `MATMPIAIJ`

278:   Note:
279:   The matrix rootname should not be confused with the base type of the function `PetscObjectBaseTypeCompare()`

281:   Developer Note:
282:   PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate `VecType` based on the
283:       size of the communicator but it is implemented by simply having additional `VecCreate_RootName()` registerer routines that dispatch to the
284:       appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is
285:       confusing.

287:   Level: developer

289: .seealso: `Mat`, `MatType`, `PetscObjectBaseTypeCompare()`
290: @*/
291: PetscErrorCode MatRegisterRootName(const char rname[], const char sname[], const char mname[])
292: {
293:   MatRootName names;

295:   PetscNew(&names);
296:   PetscStrallocpy(rname, &names->rname);
297:   PetscStrallocpy(sname, &names->sname);
298:   PetscStrallocpy(mname, &names->mname);
299:   if (!MatRootNameList) {
300:     MatRootNameList = names;
301:   } else {
302:     MatRootName next = MatRootNameList;
303:     while (next->next) next = next->next;
304:     next->next = names;
305:   }
306:   return 0;
307: }