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: {
 31:   PetscBool      found = PETSC_FALSE;
 32:   MatRootName    names = MatRootNameList;
 33:   MatType        inType;
 34:   PetscMPIInt    size;

 38:   MatGetType(mat,&inType);
 39:   MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);
 40:   while (names) {
 41:     if (size > 1) {PetscStrcmp(inType,names->mname,&found);}
 42:     else {PetscStrcmp(inType,names->sname,&found);}
 43:     if (found) {
 44:       found     = PETSC_TRUE;
 45:       *rootType = names->rname;
 46:       break;
 47:     }
 48:     names = names->next;
 49:   }
 50:   if (!found) *rootType = inType;
 51:   return(0);
 52: }

 54: /*@C
 55:    MatSetType - Builds matrix object for a particular matrix type

 57:    Collective on Mat

 59:    Input Parameters:
 60: +  mat      - the matrix object
 61: -  matype   - matrix type

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

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

 70:   Level: intermediate

 72: .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
 73: @*/
 74: PetscErrorCode  MatSetType(Mat mat, MatType matype)
 75: {
 76:   PetscErrorCode ierr,(*r)(Mat);
 77:   PetscBool      sametype,found,subclass = PETSC_FALSE;
 78:   MatRootName    names = MatRootNameList;


 83:   while (names) {
 84:     PetscStrcmp(matype,names->rname,&found);
 85:     if (found) {
 86:       PetscMPIInt size;
 87:       MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);
 88:       if (size == 1) matype = names->sname;
 89:       else matype = names->mname;
 90:       break;
 91:     }
 92:     names = names->next;
 93:   }

 95:   PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);
 96:   if (sametype) return(0);

 98:   PetscFunctionListFind(MatList,matype,&r);
 99:   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);

101:   if (mat->assembled && ((PetscObject)mat)->type_name) {
102:     PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);
103:   }
104:   if (subclass) {
105:     MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);
106:     return(0);
107:   }
108:   if (mat->ops->destroy) {
109:     /* free the old data structure if it existed */
110:     (*mat->ops->destroy)(mat);
111:     mat->ops->destroy = NULL;

113:     /* should these null spaces be removed? */
114:     MatNullSpaceDestroy(&mat->nullsp);
115:     MatNullSpaceDestroy(&mat->nearnullsp);
116:   }
117:   PetscMemzero(mat->ops,sizeof(struct _MatOps));
118:   mat->preallocated  = PETSC_FALSE;
119:   mat->assembled     = PETSC_FALSE;
120:   mat->was_assembled = PETSC_FALSE;

122:   /*
123:    Increment, rather than reset these: the object is logically the same, so its logging and
124:    state is inherited.  Furthermore, resetting makes it possible for the same state to be
125:    obtained with a different structure, confusing the PC.
126:   */
127:   mat->nonzerostate++;
128:   PetscObjectStateIncrease((PetscObject)mat);

130:   /* create the new data structure */
131:   (*r)(mat);
132:   return(0);
133: }

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

138:    Not Collective

140:    Input Parameter:
141: .  mat - the matrix

143:    Output Parameter:
144: .  name - name of matrix type

146:    Level: intermediate

148: .seealso: MatSetType()
149: @*/
150: PetscErrorCode  MatGetType(Mat mat,MatType *type)
151: {
155:   *type = ((PetscObject)mat)->type_name;
156:   return(0);
157: }

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

162:    Not Collective

164:    Input Parameter:
165: .  mat - the matrix

167:    Output Parameter:
168: .  name - name of vector type

170:    Level: intermediate

172: .seealso: MatSetVecType()
173: @*/
174: PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
175: {
179:   *vtype = mat->defaultvectype;
180:   return(0);
181: }

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

186:    Collective on Mat

188:    Input Parameters:
189: +  mat   - the matrix object
190: -  vtype - vector type

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

195:   Level: intermediate

197: .seealso: VecSetType(), MatGetVecType()
198: @*/
199: PetscErrorCode MatSetVecType(Mat mat,VecType vtype)
200: {

205:   PetscFree(mat->defaultvectype);
206:   PetscStrallocpy(vtype,&mat->defaultvectype);
207:   return(0);
208: }

210: /*@C
211:   MatRegister -  - Adds a new matrix type

213:    Not Collective

215:    Input Parameters:
216: +  name - name of a new user-defined matrix type
217: -  routine_create - routine to create method context

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

222:    Sample usage:
223: .vb
224:    MatRegister("my_mat",MyMatCreate);
225: .ve

227:    Then, your solver can be chosen with the procedural interface via
228: $     MatSetType(Mat,"my_mat")
229:    or at runtime via the option
230: $     -mat_type my_mat

232:    Level: advanced

234: .seealso: MatRegisterAll()

236:   Level: advanced
237: @*/
238: PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
239: {

243:   MatInitializePackage();
244:   PetscFunctionListAdd(&MatList,sname,function);
245:   return(0);
246: }

248: MatRootName MatRootNameList = NULL;

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

255:   Input Parameters:
256: +     rname - the rootname, for example, MATAIJ
257: .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
258: -     mname - the name of the parallel matrix type, for example, MATMPIAIJ

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

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

267:   Level: developer

269: .seealso: PetscObjectBaseTypeCompare()

271: @*/
272: PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
273: {
275:   MatRootName    names;

278:   PetscNew(&names);
279:   PetscStrallocpy(rname,&names->rname);
280:   PetscStrallocpy(sname,&names->sname);
281:   PetscStrallocpy(mname,&names->mname);
282:   if (!MatRootNameList) {
283:     MatRootNameList = names;
284:   } else {
285:     MatRootName next = MatRootNameList;
286:     while (next->next) next = next->next;
287:     next->next = names;
288:   }
289:   return(0);
290: }