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