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:    Notes:
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:   if (mat->ops->destroy) {
139:     /* free the old data structure if it existed */
140:     (*mat->ops->destroy)(mat);
141:     mat->ops->destroy = NULL;

143:     /* should these null spaces be removed? */
144:     MatNullSpaceDestroy(&mat->nullsp);
145:     MatNullSpaceDestroy(&mat->nearnullsp);
146:   }
147:   PetscMemzero(mat->ops,sizeof(struct _MatOps));
148:   mat->preallocated  = PETSC_FALSE;
149:   mat->assembled     = PETSC_FALSE;
150:   mat->was_assembled = PETSC_FALSE;

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

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

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

168:    Not Collective

170:    Input Parameter:
171: .  mat - the matrix

173:    Output Parameter:
174: .  name - name of matrix type

176:    Level: intermediate

178: .seealso: MatSetType()
179: @*/
180: PetscErrorCode  MatGetType(Mat mat,MatType *type)
181: {
184:   *type = ((PetscObject)mat)->type_name;
185:   return 0;
186: }

188: /*@C
189:    MatGetVecType - Gets the vector type used by the matrix object.

191:    Not Collective

193:    Input Parameter:
194: .  mat - the matrix

196:    Output Parameter:
197: .  name - name of vector type

199:    Level: intermediate

201: .seealso: MatSetVecType()
202: @*/
203: PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
204: {
207:   *vtype = mat->defaultvectype;
208:   return 0;
209: }

211: /*@C
212:    MatSetVecType - Set the vector type to be used for a matrix object

214:    Collective on Mat

216:    Input Parameters:
217: +  mat   - the matrix object
218: -  vtype - vector type

220:    Notes:
221:      This is rarely needed in practice since each matrix object internally sets the proper vector type.

223:   Level: intermediate

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

235: /*@C
236:   MatRegister -  - Adds a new matrix type

238:    Not Collective

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

244:    Notes:
245:    MatRegister() may be called multiple times to add several user-defined solvers.

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

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

257:    Level: advanced

259: .seealso: MatRegisterAll()

261:   Level: advanced
262: @*/
263: PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
264: {
265:   MatInitializePackage();
266:   PetscFunctionListAdd(&MatList,sname,function);
267:   return 0;
268: }

270: MatRootName MatRootNameList = NULL;

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

277:   Input Parameters:
278: +     rname - the rootname, for example, MATAIJ
279: .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
280: -     mname - the name of the parallel matrix type, for example, MATMPIAIJ

282:   Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare()

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

289:   Level: developer

291: .seealso: PetscObjectBaseTypeCompare()

293: @*/
294: PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
295: {
296:   MatRootName    names;

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