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 Notes: 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 if (mat->ops->destroy) { 142 /* free the old data structure if it existed */ 143 PetscCall((*mat->ops->destroy)(mat)); 144 mat->ops->destroy = NULL; 145 146 /* should these null spaces be removed? */ 147 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 148 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 149 } 150 PetscCall(PetscMemzero(mat->ops,sizeof(struct _MatOps))); 151 mat->preallocated = PETSC_FALSE; 152 mat->assembled = PETSC_FALSE; 153 mat->was_assembled = PETSC_FALSE; 154 155 /* 156 Increment, rather than reset these: the object is logically the same, so its logging and 157 state is inherited. Furthermore, resetting makes it possible for the same state to be 158 obtained with a different structure, confusing the PC. 159 */ 160 mat->nonzerostate++; 161 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 162 163 /* create the new data structure */ 164 PetscCall((*r)(mat)); 165 PetscFunctionReturn(0); 166 } 167 168 /*@C 169 MatGetType - Gets the matrix type as a string from the matrix object. 170 171 Not Collective 172 173 Input Parameter: 174 . mat - the matrix 175 176 Output Parameter: 177 . name - name of matrix type 178 179 Level: intermediate 180 181 .seealso: `MatSetType()` 182 @*/ 183 PetscErrorCode MatGetType(Mat mat,MatType *type) 184 { 185 PetscFunctionBegin; 186 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 187 PetscValidPointer(type,2); 188 *type = ((PetscObject)mat)->type_name; 189 PetscFunctionReturn(0); 190 } 191 192 /*@C 193 MatGetVecType - Gets the vector type used by the matrix object. 194 195 Not Collective 196 197 Input Parameter: 198 . mat - the matrix 199 200 Output Parameter: 201 . name - name of vector type 202 203 Level: intermediate 204 205 .seealso: `MatSetVecType()` 206 @*/ 207 PetscErrorCode MatGetVecType(Mat mat,VecType *vtype) 208 { 209 PetscFunctionBegin; 210 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 211 PetscValidPointer(vtype,2); 212 *vtype = mat->defaultvectype; 213 PetscFunctionReturn(0); 214 } 215 216 /*@C 217 MatSetVecType - Set the vector type to be used for a matrix object 218 219 Collective on Mat 220 221 Input Parameters: 222 + mat - the matrix object 223 - vtype - vector type 224 225 Notes: 226 This is rarely needed in practice since each matrix object internally sets the proper vector type. 227 228 Level: intermediate 229 230 .seealso: `VecSetType()`, `MatGetVecType()` 231 @*/ 232 PetscErrorCode MatSetVecType(Mat mat,VecType vtype) 233 { 234 PetscFunctionBegin; 235 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 236 PetscCall(PetscFree(mat->defaultvectype)); 237 PetscCall(PetscStrallocpy(vtype,&mat->defaultvectype)); 238 PetscFunctionReturn(0); 239 } 240 241 /*@C 242 MatRegister - - Adds a new matrix type 243 244 Not Collective 245 246 Input Parameters: 247 + name - name of a new user-defined matrix type 248 - routine_create - routine to create method context 249 250 Notes: 251 MatRegister() may be called multiple times to add several user-defined solvers. 252 253 Sample usage: 254 .vb 255 MatRegister("my_mat",MyMatCreate); 256 .ve 257 258 Then, your solver can be chosen with the procedural interface via 259 $ MatSetType(Mat,"my_mat") 260 or at runtime via the option 261 $ -mat_type my_mat 262 263 Level: advanced 264 265 .seealso: `MatRegisterAll()` 266 267 Level: advanced 268 @*/ 269 PetscErrorCode MatRegister(const char sname[],PetscErrorCode (*function)(Mat)) 270 { 271 PetscFunctionBegin; 272 PetscCall(MatInitializePackage()); 273 PetscCall(PetscFunctionListAdd(&MatList,sname,function)); 274 PetscFunctionReturn(0); 275 } 276 277 MatRootName MatRootNameList = NULL; 278 279 /*@C 280 MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType() 281 and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the 282 matrix. 283 284 Input Parameters: 285 + rname - the rootname, for example, MATAIJ 286 . sname - the name of the sequential matrix type, for example, MATSEQAIJ 287 - mname - the name of the parallel matrix type, for example, MATMPIAIJ 288 289 Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare() 290 291 Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the 292 size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the 293 appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is 294 confusing. 295 296 Level: developer 297 298 .seealso: `PetscObjectBaseTypeCompare()` 299 300 @*/ 301 PetscErrorCode MatRegisterRootName(const char rname[],const char sname[],const char mname[]) 302 { 303 MatRootName names; 304 305 PetscFunctionBegin; 306 PetscCall(PetscNew(&names)); 307 PetscCall(PetscStrallocpy(rname,&names->rname)); 308 PetscCall(PetscStrallocpy(sname,&names->sname)); 309 PetscCall(PetscStrallocpy(mname,&names->mname)); 310 if (!MatRootNameList) { 311 MatRootNameList = names; 312 } else { 313 MatRootName next = MatRootNameList; 314 while (next->next) next = next->next; 315 next->next = names; 316 } 317 PetscFunctionReturn(0); 318 } 319