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