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 = NULL; 13 14 /* MatGetRootType_Private - Gets the root type of the input matrix's type (e.g., MATAIJ for MATSEQAIJ) 15 16 Not Collective 17 18 Input Parameters: 19 . mat - the input matrix, could be sequential or MPI 20 21 Output Parameters: 22 . rootType - the root matrix type 23 24 Level: developer 25 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; 33 34 PetscFunctionBegin; 35 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 36 PetscCall(MatGetType(mat,&inType)); 37 while (names) { 38 PetscCall(PetscStrcmp(inType,names->mname,&found)); 39 if (!found) PetscCall(PetscStrcmp(inType,names->sname,&found)); 40 if (found) { 41 found = PETSC_TRUE; 42 *rootType = names->rname; 43 break; 44 } 45 names = names->next; 46 } 47 if (!found) *rootType = inType; 48 PetscFunctionReturn(0); 49 } 50 51 /*@C 52 MatSetType - Builds matrix object for a particular matrix type 53 54 Collective on Mat 55 56 Input Parameters: 57 + mat - the matrix object 58 - matype - matrix type 59 60 Options Database Key: 61 . -mat_type <method> - Sets the type; use -help for a list 62 of available methods (for instance, seqaij) 63 64 Notes: 65 See "${PETSC_DIR}/include/petscmat.h" for available methods 66 67 Level: intermediate 68 69 .seealso: `PCSetType()`, `VecSetType()`, `MatCreate()`, `MatType`, `Mat` 70 @*/ 71 PetscErrorCode MatSetType(Mat mat, MatType matype) 72 { 73 PetscBool sametype,found,subclass = PETSC_FALSE; 74 MatRootName names = MatRootNameList; 75 PetscErrorCode (*r)(Mat); 76 77 PetscFunctionBegin; 78 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 79 80 while (names) { 81 PetscCall(PetscStrcmp(matype,names->rname,&found)); 82 if (found) { 83 PetscMPIInt size; 84 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size)); 85 if (size == 1) matype = names->sname; 86 else matype = names->mname; 87 break; 88 } 89 names = names->next; 90 } 91 92 PetscCall(PetscObjectTypeCompare((PetscObject)mat,matype,&sametype)); 93 if (sametype) PetscFunctionReturn(0); 94 95 PetscCall(PetscFunctionListFind(MatList,matype,&r)); 96 PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 97 98 if (mat->assembled && ((PetscObject)mat)->type_name) PetscCall(PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass)); 99 if (subclass) { 100 PetscCall(MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat)); 101 PetscFunctionReturn(0); 102 } 103 if (mat->ops->destroy) { 104 /* free the old data structure if it existed */ 105 PetscCall((*mat->ops->destroy)(mat)); 106 mat->ops->destroy = NULL; 107 108 /* should these null spaces be removed? */ 109 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 110 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 111 } 112 PetscCall(PetscMemzero(mat->ops,sizeof(struct _MatOps))); 113 mat->preallocated = PETSC_FALSE; 114 mat->assembled = PETSC_FALSE; 115 mat->was_assembled = PETSC_FALSE; 116 117 /* 118 Increment, rather than reset these: the object is logically the same, so its logging and 119 state is inherited. Furthermore, resetting makes it possible for the same state to be 120 obtained with a different structure, confusing the PC. 121 */ 122 mat->nonzerostate++; 123 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 124 125 /* create the new data structure */ 126 PetscCall((*r)(mat)); 127 PetscFunctionReturn(0); 128 } 129 130 /*@C 131 MatGetType - Gets the matrix type as a string from the matrix object. 132 133 Not Collective 134 135 Input Parameter: 136 . mat - the matrix 137 138 Output Parameter: 139 . name - name of matrix type 140 141 Level: intermediate 142 143 .seealso: `MatSetType()` 144 @*/ 145 PetscErrorCode MatGetType(Mat mat,MatType *type) 146 { 147 PetscFunctionBegin; 148 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 149 PetscValidPointer(type,2); 150 *type = ((PetscObject)mat)->type_name; 151 PetscFunctionReturn(0); 152 } 153 154 /*@C 155 MatGetVecType - Gets the vector type used by the matrix object. 156 157 Not Collective 158 159 Input Parameter: 160 . mat - the matrix 161 162 Output Parameter: 163 . name - name of vector type 164 165 Level: intermediate 166 167 .seealso: `MatSetVecType()` 168 @*/ 169 PetscErrorCode MatGetVecType(Mat mat,VecType *vtype) 170 { 171 PetscFunctionBegin; 172 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 173 PetscValidPointer(vtype,2); 174 *vtype = mat->defaultvectype; 175 PetscFunctionReturn(0); 176 } 177 178 /*@C 179 MatSetVecType - Set the vector type to be used for a matrix object 180 181 Collective on Mat 182 183 Input Parameters: 184 + mat - the matrix object 185 - vtype - vector type 186 187 Notes: 188 This is rarely needed in practice since each matrix object internally sets the proper vector type. 189 190 Level: intermediate 191 192 .seealso: `VecSetType()`, `MatGetVecType()` 193 @*/ 194 PetscErrorCode MatSetVecType(Mat mat,VecType vtype) 195 { 196 PetscFunctionBegin; 197 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 198 PetscCall(PetscFree(mat->defaultvectype)); 199 PetscCall(PetscStrallocpy(vtype,&mat->defaultvectype)); 200 PetscFunctionReturn(0); 201 } 202 203 /*@C 204 MatRegister - - Adds a new matrix type 205 206 Not Collective 207 208 Input Parameters: 209 + name - name of a new user-defined matrix type 210 - routine_create - routine to create method context 211 212 Notes: 213 MatRegister() may be called multiple times to add several user-defined solvers. 214 215 Sample usage: 216 .vb 217 MatRegister("my_mat",MyMatCreate); 218 .ve 219 220 Then, your solver can be chosen with the procedural interface via 221 $ MatSetType(Mat,"my_mat") 222 or at runtime via the option 223 $ -mat_type my_mat 224 225 Level: advanced 226 227 .seealso: `MatRegisterAll()` 228 229 Level: advanced 230 @*/ 231 PetscErrorCode MatRegister(const char sname[],PetscErrorCode (*function)(Mat)) 232 { 233 PetscFunctionBegin; 234 PetscCall(MatInitializePackage()); 235 PetscCall(PetscFunctionListAdd(&MatList,sname,function)); 236 PetscFunctionReturn(0); 237 } 238 239 MatRootName MatRootNameList = NULL; 240 241 /*@C 242 MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType() 243 and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the 244 matrix. 245 246 Input Parameters: 247 + rname - the rootname, for example, MATAIJ 248 . sname - the name of the sequential matrix type, for example, MATSEQAIJ 249 - mname - the name of the parallel matrix type, for example, MATMPIAIJ 250 251 Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare() 252 253 Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the 254 size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the 255 appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is 256 confusing. 257 258 Level: developer 259 260 .seealso: `PetscObjectBaseTypeCompare()` 261 262 @*/ 263 PetscErrorCode MatRegisterRootName(const char rname[],const char sname[],const char mname[]) 264 { 265 MatRootName names; 266 267 PetscFunctionBegin; 268 PetscCall(PetscNew(&names)); 269 PetscCall(PetscStrallocpy(rname,&names->rname)); 270 PetscCall(PetscStrallocpy(sname,&names->sname)); 271 PetscCall(PetscStrallocpy(mname,&names->mname)); 272 if (!MatRootNameList) { 273 MatRootNameList = names; 274 } else { 275 MatRootName next = MatRootNameList; 276 while (next->next) next = next->next; 277 next->next = names; 278 } 279 PetscFunctionReturn(0); 280 } 281