Actual source code: matreg.c

petsc-3.11.4 2019-09-28
Report Typos and Errors

  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 = 0;

 14: /*@C
 15:    MatSetType - Builds matrix object for a particular matrix type

 17:    Collective on Mat

 19:    Input Parameters:
 20: +  mat      - the matrix object
 21: -  matype   - matrix type

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

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

 30:   Level: intermediate

 32: .keywords: Mat, MatType, set, method

 34: .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
 35: @*/
 36: PetscErrorCode  MatSetType(Mat mat, MatType matype)
 37: {
 38:   PetscErrorCode ierr,(*r)(Mat);
 39:   PetscBool      sametype,found,subclass = PETSC_FALSE;
 40:   MatRootName    names = MatRootNameList;


 45:   while (names) {
 46:     PetscStrcmp(matype,names->rname,&found);
 47:     if (found) {
 48:       PetscMPIInt size;
 49:       MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);
 50:       if (size == 1) matype = names->sname;
 51:       else matype = names->mname;
 52:       break;
 53:     }
 54:     names = names->next;
 55:   }

 57:   PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);
 58:   if (sametype) return(0);

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

 63:   if (mat->assembled && ((PetscObject)mat)->type_name) {
 64:     PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);
 65:   }
 66:   if (subclass) {
 67:     MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);
 68:     return(0);
 69:   } if (mat->ops->destroy) {
 70:     /* free the old data structure if it existed */
 71:     (*mat->ops->destroy)(mat);
 72:     mat->ops->destroy = NULL;

 74:     /* should these null spaces be removed? */
 75:     MatNullSpaceDestroy(&mat->nullsp);
 76:     MatNullSpaceDestroy(&mat->nearnullsp);
 77:     mat->preallocated = PETSC_FALSE;
 78:     mat->assembled = PETSC_FALSE;
 79:     mat->was_assembled = PETSC_FALSE;

 81:     /*
 82:      Increment, rather than reset these: the object is logically the same, so its logging and
 83:      state is inherited.  Furthermore, resetting makes it possible for the same state to be
 84:      obtained with a different structure, confusing the PC.
 85:     */
 86:     ++mat->nonzerostate;
 87:     PetscObjectStateIncrease((PetscObject)mat);
 88:   }
 89:   mat->preallocated  = PETSC_FALSE;
 90:   mat->assembled     = PETSC_FALSE;
 91:   mat->was_assembled = PETSC_FALSE;

 93:   /* increase the state so that any code holding the current state knows the matrix has been changed */
 94:   mat->nonzerostate++;
 95:   PetscObjectStateIncrease((PetscObject)mat);

 97:   /* create the new data structure */
 98:   (*r)(mat);
 99:   return(0);
100: }

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

105:    Not Collective

107:    Input Parameter:
108: .  mat - the matrix

110:    Output Parameter:
111: .  name - name of matrix type

113:    Level: intermediate

115: .keywords: Mat, MatType, get, method, name

117: .seealso: MatSetType()
118: @*/
119: PetscErrorCode  MatGetType(Mat mat,MatType *type)
120: {
124:   *type = ((PetscObject)mat)->type_name;
125:   return(0);
126: }


129: /*@C
130:   MatRegister -  - Adds a new matrix type

132:    Not Collective

134:    Input Parameters:
135: +  name - name of a new user-defined matrix type
136: -  routine_create - routine to create method context

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

141:    Sample usage:
142: .vb
143:    MatRegister("my_mat",MyMatCreate);
144: .ve

146:    Then, your solver can be chosen with the procedural interface via
147: $     MatSetType(Mat,"my_mat")
148:    or at runtime via the option
149: $     -mat_type my_mat

151:    Level: advanced

153: .keywords: Mat, register

155: .seealso: MatRegisterAll()


158:   Level: advanced
159: @*/
160: PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
161: {

165:   MatInitializePackage();
166:   PetscFunctionListAdd(&MatList,sname,function);
167:   return(0);
168: }

170: MatRootName MatRootNameList = 0;

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

177:   Input Parameters:
178: +     rname - the rootname, for example, MATAIJ
179: .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
180: -     mname - the name of the parallel matrix type, for example, MATMPIAIJ

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

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

189:   Level: developer

191: .seealso: PetscObjectBaseTypeCompare()

193: @*/
194: PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
195: {
197:   MatRootName    names;

200:   PetscNew(&names);
201:   PetscStrallocpy(rname,&names->rname);
202:   PetscStrallocpy(sname,&names->sname);
203:   PetscStrallocpy(mname,&names->mname);
204:   if (!MatRootNameList) {
205:     MatRootNameList = names;
206:   } else {
207:     MatRootName next = MatRootNameList;
208:     while (next->next) next = next->next;
209:     next->next = names;
210:   }
211:   return(0);
212: }