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: /*@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: .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
     33: @*/
     34: PetscErrorCode  MatSetType(Mat mat, MatType matype)
     35: {
     36:   PetscErrorCode ierr,(*r)(Mat);
     37:   PetscBool      sametype,found,subclass = PETSC_FALSE;
     38:   MatRootName    names = MatRootNameList;

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

     55:   PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);
     56:   if (sametype) return(0);

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

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

     73:     /* should these null spaces be removed? */
     74:     MatNullSpaceDestroy(&mat->nullsp);
     75:     MatNullSpaceDestroy(&mat->nearnullsp);
     76:   }
     77:   PetscMemzero(mat->ops,sizeof(struct _MatOps));
     78:   mat->preallocated  = PETSC_FALSE;
     79:   mat->assembled     = PETSC_FALSE;
     80:   mat->was_assembled = PETSC_FALSE;

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

     90:   /* create the new data structure */
     91:   (*r)(mat);
     92:   return(0);
     93: }

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

     98:    Not Collective

    100:    Input Parameter:
    101: .  mat - the matrix

    103:    Output Parameter:
    104: .  name - name of matrix type

    106:    Level: intermediate

    108: .seealso: MatSetType()
    109: @*/
    110: PetscErrorCode  MatGetType(Mat mat,MatType *type)
    111: {
    115:   *type = ((PetscObject)mat)->type_name;
    116:   return(0);
    117: }

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

    122:    Not Collective

    124:    Input Parameter:
    125: .  mat - the matrix

    127:    Output Parameter:
    128: .  name - name of vector type

    130:    Level: intermediate

    132: .seealso: MatSetVecType()
    133: @*/
    134: PetscErrorCode MatGetVecType(Mat mat,VecType *vtype)
    135: {
    139:   *vtype = mat->defaultvectype;
    140:   return(0);
    141: }

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

    146:    Collective on Mat

    148:    Input Parameters:
    149: +  mat   - the matrix object
    150: -  vtype - vector type

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

    155:   Level: intermediate

    157: .seealso: VecSetType(), MatGetVecType()
    158: @*/
    159: PetscErrorCode MatSetVecType(Mat mat,VecType vtype)
    160: {

    165:   PetscFree(mat->defaultvectype);
    166:   PetscStrallocpy(vtype,&mat->defaultvectype);
    167:   return(0);
    168: }

    170: /*@C
    171:   MatRegister -  - Adds a new matrix type

    173:    Not Collective

    175:    Input Parameters:
    176: +  name - name of a new user-defined matrix type
    177: -  routine_create - routine to create method context

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

    182:    Sample usage:
    183: .vb
    184:    MatRegister("my_mat",MyMatCreate);
    185: .ve

    187:    Then, your solver can be chosen with the procedural interface via
    188: $     MatSetType(Mat,"my_mat")
    189:    or at runtime via the option
    190: $     -mat_type my_mat

    192:    Level: advanced

    194: .seealso: MatRegisterAll()

    197:   Level: advanced
    198: @*/
    199: PetscErrorCode  MatRegister(const char sname[],PetscErrorCode (*function)(Mat))
    200: {

    204:   MatInitializePackage();
    205:   PetscFunctionListAdd(&MatList,sname,function);
    206:   return(0);
    207: }

    209: MatRootName MatRootNameList = NULL;

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

    216:   Input Parameters:
    217: +     rname - the rootname, for example, MATAIJ
    218: .     sname - the name of the sequential matrix type, for example, MATSEQAIJ
    219: -     mname - the name of the parallel matrix type, for example, MATMPIAIJ

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

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

    228:   Level: developer

    230: .seealso: PetscObjectBaseTypeCompare()

    232: @*/
    233: PetscErrorCode  MatRegisterRootName(const char rname[],const char sname[],const char mname[])
    234: {
    236:   MatRootName    names;

    239:   PetscNew(&names);
    240:   PetscStrallocpy(rname,&names->rname);
    241:   PetscStrallocpy(sname,&names->sname);
    242:   PetscStrallocpy(mname,&names->mname);
    243:   if (!MatRootNameList) {
    244:     MatRootNameList = names;
    245:   } else {
    246:     MatRootName next = MatRootNameList;
    247:     while (next->next) next = next->next;
    248:     next->next = names;
    249:   }
    250:   return(0);
    251: }