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