1 2 /* 3 Mechanism for register PETSc matrix types 4 */ 5 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 6 7 PetscBool MatRegisterAllCalled = PETSC_FALSE; 8 9 /* 10 Contains the list of registered Mat routines 11 */ 12 PetscFunctionList MatList = 0; 13 14 /*@C 15 MatSetType - Builds matrix object for a particular matrix type 16 17 Collective on Mat 18 19 Input Parameters: 20 + mat - the matrix object 21 - matype - matrix type 22 23 Options Database Key: 24 . -mat_type <method> - Sets the type; use -help for a list 25 of available methods (for instance, seqaij) 26 27 Notes: 28 See "${PETSC_DIR}/include/petscmat.h" for available methods 29 30 Level: intermediate 31 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; 39 40 PetscFunctionBegin; 41 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 42 43 while (names) { 44 ierr = PetscStrcmp(matype,names->rname,&found);CHKERRQ(ierr); 45 if (found) { 46 PetscMPIInt size; 47 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr); 48 if (size == 1) matype = names->sname; 49 else matype = names->mname; 50 break; 51 } 52 names = names->next; 53 } 54 55 ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr); 56 if (sametype) PetscFunctionReturn(0); 57 58 ierr = PetscFunctionListFind(MatList,matype,&r);CHKERRQ(ierr); 59 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 60 61 if (mat->assembled && ((PetscObject)mat)->type_name) { 62 ierr = PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);CHKERRQ(ierr); 63 } 64 if (subclass) { 65 ierr = MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr); 66 PetscFunctionReturn(0); 67 } if (mat->ops->destroy) { 68 /* free the old data structure if it existed */ 69 ierr = (*mat->ops->destroy)(mat);CHKERRQ(ierr); 70 mat->ops->destroy = NULL; 71 72 /* should these null spaces be removed? */ 73 ierr = MatNullSpaceDestroy(&mat->nullsp);CHKERRQ(ierr); 74 ierr = MatNullSpaceDestroy(&mat->nearnullsp);CHKERRQ(ierr); 75 mat->preallocated = PETSC_FALSE; 76 mat->assembled = PETSC_FALSE; 77 mat->was_assembled = PETSC_FALSE; 78 79 /* 80 Increment, rather than reset these: the object is logically the same, so its logging and 81 state is inherited. Furthermore, resetting makes it possible for the same state to be 82 obtained with a different structure, confusing the PC. 83 */ 84 ++mat->nonzerostate; 85 ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr); 86 } 87 mat->preallocated = PETSC_FALSE; 88 mat->assembled = PETSC_FALSE; 89 mat->was_assembled = PETSC_FALSE; 90 91 /* increase the state so that any code holding the current state knows the matrix has been changed */ 92 mat->nonzerostate++; 93 ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr); 94 95 /* create the new data structure */ 96 ierr = (*r)(mat);CHKERRQ(ierr); 97 PetscFunctionReturn(0); 98 } 99 100 /*@C 101 MatGetType - Gets the matrix type as a string from the matrix object. 102 103 Not Collective 104 105 Input Parameter: 106 . mat - the matrix 107 108 Output Parameter: 109 . name - name of matrix type 110 111 Level: intermediate 112 113 .seealso: MatSetType() 114 @*/ 115 PetscErrorCode MatGetType(Mat mat,MatType *type) 116 { 117 PetscFunctionBegin; 118 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 119 PetscValidPointer(type,2); 120 *type = ((PetscObject)mat)->type_name; 121 PetscFunctionReturn(0); 122 } 123 124 125 /*@C 126 MatRegister - - Adds a new matrix type 127 128 Not Collective 129 130 Input Parameters: 131 + name - name of a new user-defined matrix type 132 - routine_create - routine to create method context 133 134 Notes: 135 MatRegister() may be called multiple times to add several user-defined solvers. 136 137 Sample usage: 138 .vb 139 MatRegister("my_mat",MyMatCreate); 140 .ve 141 142 Then, your solver can be chosen with the procedural interface via 143 $ MatSetType(Mat,"my_mat") 144 or at runtime via the option 145 $ -mat_type my_mat 146 147 Level: advanced 148 149 .seealso: MatRegisterAll() 150 151 152 Level: advanced 153 @*/ 154 PetscErrorCode MatRegister(const char sname[],PetscErrorCode (*function)(Mat)) 155 { 156 PetscErrorCode ierr; 157 158 PetscFunctionBegin; 159 ierr = MatInitializePackage();CHKERRQ(ierr); 160 ierr = PetscFunctionListAdd(&MatList,sname,function);CHKERRQ(ierr); 161 PetscFunctionReturn(0); 162 } 163 164 MatRootName MatRootNameList = 0; 165 166 /*@C 167 MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType() 168 and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the 169 matrix. 170 171 Input Parameters: 172 + rname - the rootname, for example, MATAIJ 173 . sname - the name of the sequential matrix type, for example, MATSEQAIJ 174 - mname - the name of the parallel matrix type, for example, MATMPIAIJ 175 176 Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare() 177 178 Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the 179 size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the 180 appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is 181 confusing. 182 183 Level: developer 184 185 .seealso: PetscObjectBaseTypeCompare() 186 187 @*/ 188 PetscErrorCode MatRegisterRootName(const char rname[],const char sname[],const char mname[]) 189 { 190 PetscErrorCode ierr; 191 MatRootName names; 192 193 PetscFunctionBegin; 194 ierr = PetscNew(&names);CHKERRQ(ierr); 195 ierr = PetscStrallocpy(rname,&names->rname);CHKERRQ(ierr); 196 ierr = PetscStrallocpy(sname,&names->sname);CHKERRQ(ierr); 197 ierr = PetscStrallocpy(mname,&names->mname);CHKERRQ(ierr); 198 if (!MatRootNameList) { 199 MatRootNameList = names; 200 } else { 201 MatRootName next = MatRootNameList; 202 while (next->next) next = next->next; 203 next->next = names; 204 } 205 PetscFunctionReturn(0); 206 } 207 208 209 210 211 212 213 214