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: /*@C
 51:    MatSetType - Builds matrix object for a particular matrix type

 53:    Collective on Mat

 55:    Input Parameters:
 56: +  mat      - the matrix object
 57: -  matype   - matrix type

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

 63:    Notes:
 64:    See "${PETSC_DIR}/include/petscmat.h" for available methods

 66:   Level: intermediate

 68: .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
 69: @*/
 70: PetscErrorCode  MatSetType(Mat mat, MatType matype)
 71: {
 72:   PetscBool      sametype,found,subclass = PETSC_FALSE;
 73:   MatRootName    names = MatRootNameList;
 74:   PetscErrorCode (*r)(Mat);


 78:   while (names) {
 79:     PetscStrcmp(matype,names->rname,&found);
 80:     if (found) {
 81:       PetscMPIInt size;
 82:       MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);
 83:       if (size == 1) matype = names->sname;
 84:       else matype = names->mname;
 85:       break;
 86:     }
 87:     names = names->next;
 88:   }

 90:   PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);
 91:   if (sametype) return 0;

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

 96:   if (mat->assembled && ((PetscObject)mat)->type_name) PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);
 97:   if (subclass) {
 98:     MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);
 99:     return 0;
100:   }
101:   if (mat->ops->destroy) {
102:     /* free the old data structure if it existed */
103:     (*mat->ops->destroy)(mat);
104:     mat->ops->destroy = NULL;

106:     /* should these null spaces be removed? */
107:     MatNullSpaceDestroy(&mat->nullsp);
108:     MatNullSpaceDestroy(&mat->nearnullsp);
109:   }
110:   PetscMemzero(mat->ops,sizeof(struct _MatOps));
111:   mat->preallocated  = PETSC_FALSE;
112:   mat->assembled     = PETSC_FALSE;
113:   mat->was_assembled = PETSC_FALSE;

115:   /*
116:    Increment, rather than reset these: the object is logically the same, so its logging and
117:    state is inherited.  Furthermore, resetting makes it possible for the same state to be
118:    obtained with a different structure, confusing the PC.
119:   */
120:   mat->nonzerostate++;
121:   PetscObjectStateIncrease((PetscObject)mat);

123:   /* create the new data structure */
124:   (*r)(mat);
125:   return 0;
126: }

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

131:    Not Collective

133:    Input Parameter:
134: .  mat - the matrix

136:    Output Parameter:
137: .  name - name of matrix type

139:    Level: intermediate

141: .seealso: MatSetType()
142: @*/
143: PetscErrorCode  MatGetType(Mat mat,MatType *type)
144: {
147:   *type = ((PetscObject)mat)->type_name;
148:   return 0;
149: }

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

154:    Not Collective

156:    Input Parameter:
157: .  mat - the matrix

159:    Output Parameter:
160: .  name - name of vector type

162:    Level: intermediate

164: .seealso: MatSetVecType()
165: @*/
166: PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
167: {
170:   *vtype = mat->defaultvectype;
171:   return 0;
172: }

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

177:    Collective on Mat

179:    Input Parameters:
180: +  mat   - the matrix object
181: -  vtype - vector type

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

186:   Level: intermediate

188: .seealso: VecSetType(), MatGetVecType()
189: @*/
190: PetscErrorCode MatSetVecType(Mat mat,VecType vtype)
191: {
193:   PetscFree(mat->defaultvectype);
194:   PetscStrallocpy(vtype,&mat->defaultvectype);
195:   return 0;
196: }

198: /*@C
199:   MatRegister -  - Adds a new matrix type

201:    Not Collective

203:    Input Parameters:
204: +  name - name of a new user-defined matrix type
205: -  routine_create - routine to create method context

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

210:    Sample usage:
211: .vb
212:    MatRegister("my_mat",MyMatCreate);
213: .ve

215:    Then, your solver can be chosen with the procedural interface via
216: $     MatSetType(Mat,"my_mat")
217:    or at runtime via the option
218: $     -mat_type my_mat

220:    Level: advanced

222: .seealso: MatRegisterAll()

224:   Level: advanced
225: @*/
226: PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
227: {
228:   MatInitializePackage();
229:   PetscFunctionListAdd(&MatList,sname,function);
230:   return 0;
231: }

233: MatRootName MatRootNameList = NULL;

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

240:   Input Parameters:
241: +     rname - the rootname, for example, MATAIJ
242: .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
243: -     mname - the name of the parallel matrix type, for example, MATMPIAIJ

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

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

252:   Level: developer

254: .seealso: PetscObjectBaseTypeCompare()

256: @*/
257: PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
258: {
259:   MatRootName    names;

261:   PetscNew(&names);
262:   PetscStrallocpy(rname,&names->rname);
263:   PetscStrallocpy(sname,&names->sname);
264:   PetscStrallocpy(mname,&names->mname);
265:   if (!MatRootNameList) {
266:     MatRootNameList = names;
267:   } else {
268:     MatRootName next = MatRootNameList;
269:     while (next->next) next = next->next;
270:     next->next = names;
271:   }
272:   return 0;
273: }