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 = 0; 13 14 /*@C 15 MatSetType - Builds matrix object for a particular matrix type 16 17 Collective on Mat 18 19 Input Parameters: 20 + mat - the matrix object 21 - matype - matrix type 22 23 Options Database Key: 24 . -mat_type <method> - Sets the type; use -help for a list 25 of available methods (for instance, seqaij) 26 27 Notes: 28 See "${PETSC_DIR}/include/petscmat.h" for available methods 29 30 Level: intermediate 31 32 .keywords: Mat, MatType, set, method 33 34 .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat 35 @*/ 36 PetscErrorCode MatSetType(Mat mat, MatType matype) 37 { 38 PetscErrorCode ierr,(*r)(Mat); 39 PetscBool sametype,found,subclass = PETSC_FALSE; 40 MatRootName names = MatRootNameList; 41 42 PetscFunctionBegin; 43 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 44 45 while (names) { 46 ierr = PetscStrcmp(matype,names->rname,&found);CHKERRQ(ierr); 47 if (found) { 48 PetscMPIInt size; 49 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr); 50 if (size == 1) matype = names->sname; 51 else matype = names->mname; 52 break; 53 } 54 names = names->next; 55 } 56 57 ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr); 58 if (sametype) PetscFunctionReturn(0); 59 60 ierr = PetscFunctionListFind(MatList,matype,&r);CHKERRQ(ierr); 61 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype); 62 63 if (mat->assembled && ((PetscObject)mat)->type_name) { 64 ierr = PetscStrbeginswith(matype,((PetscObject)mat)->type_name,&subclass);CHKERRQ(ierr); 65 } 66 if (subclass) { 67 ierr = MatConvert(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr); 68 PetscFunctionReturn(0); 69 } if (mat->ops->destroy) { 70 /* free the old data structure if it existed */ 71 ierr = (*mat->ops->destroy)(mat);CHKERRQ(ierr); 72 mat->ops->destroy = NULL; 73 74 /* should these null spaces be removed? */ 75 ierr = MatNullSpaceDestroy(&mat->nullsp);CHKERRQ(ierr); 76 ierr = MatNullSpaceDestroy(&mat->nearnullsp);CHKERRQ(ierr); 77 mat->preallocated = PETSC_FALSE; 78 mat->assembled = PETSC_FALSE; 79 mat->was_assembled = PETSC_FALSE; 80 81 /* 82 Increment, rather than reset these: the object is logically the same, so its logging and 83 state is inherited. Furthermore, resetting makes it possible for the same state to be 84 obtained with a different structure, confusing the PC. 85 */ 86 ++mat->nonzerostate; 87 ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr); 88 } 89 mat->preallocated = PETSC_FALSE; 90 mat->assembled = PETSC_FALSE; 91 mat->was_assembled = PETSC_FALSE; 92 93 /* increase the state so that any code holding the current state knows the matrix has been changed */ 94 mat->nonzerostate++; 95 ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr); 96 97 /* create the new data structure */ 98 ierr = (*r)(mat);CHKERRQ(ierr); 99 PetscFunctionReturn(0); 100 } 101 102 /*@C 103 MatGetType - Gets the matrix type as a string from the matrix object. 104 105 Not Collective 106 107 Input Parameter: 108 . mat - the matrix 109 110 Output Parameter: 111 . name - name of matrix type 112 113 Level: intermediate 114 115 .keywords: Mat, MatType, get, method, name 116 117 .seealso: MatSetType() 118 @*/ 119 PetscErrorCode MatGetType(Mat mat,MatType *type) 120 { 121 PetscFunctionBegin; 122 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 123 PetscValidPointer(type,2); 124 *type = ((PetscObject)mat)->type_name; 125 PetscFunctionReturn(0); 126 } 127 128 129 /*@C 130 MatRegister - - Adds a new matrix type 131 132 Not Collective 133 134 Input Parameters: 135 + name - name of a new user-defined matrix type 136 - routine_create - routine to create method context 137 138 Notes: 139 MatRegister() may be called multiple times to add several user-defined solvers. 140 141 Sample usage: 142 .vb 143 MatRegister("my_mat",MyMatCreate); 144 .ve 145 146 Then, your solver can be chosen with the procedural interface via 147 $ MatSetType(Mat,"my_mat") 148 or at runtime via the option 149 $ -mat_type my_mat 150 151 Level: advanced 152 153 .keywords: Mat, register 154 155 .seealso: MatRegisterAll() 156 157 158 Level: advanced 159 @*/ 160 PetscErrorCode MatRegister(const char sname[],PetscErrorCode (*function)(Mat)) 161 { 162 PetscErrorCode ierr; 163 164 PetscFunctionBegin; 165 ierr = MatInitializePackage();CHKERRQ(ierr); 166 ierr = PetscFunctionListAdd(&MatList,sname,function);CHKERRQ(ierr); 167 PetscFunctionReturn(0); 168 } 169 170 MatRootName MatRootNameList = 0; 171 172 /*@C 173 MatRegisterRootName - Registers a name that can be used for either a sequential or its corresponding parallel matrix type. MatSetType() 174 and -mat_type will automatically use the sequential or parallel version based on the size of the MPI communicator associated with the 175 matrix. 176 177 Input Parameters: 178 + rname - the rootname, for example, MATAIJ 179 . sname - the name of the sequential matrix type, for example, MATSEQAIJ 180 - mname - the name of the parallel matrix type, for example, MATMPIAIJ 181 182 Notes: The matrix rootname should not be confused with the base type of the function PetscObjectBaseTypeCompare() 183 184 Developer Notes: PETSc vectors have a similar rootname that indicates PETSc should automatically select the appropriate VecType based on the 185 size of the communicator but it is implemented by simply having additional VecCreate_RootName() registerer routines that dispatch to the 186 appropriate creation routine. Why have two different ways of implementing the same functionality for different types of objects? It is 187 confusing. 188 189 Level: developer 190 191 .seealso: PetscObjectBaseTypeCompare() 192 193 @*/ 194 PetscErrorCode MatRegisterRootName(const char rname[],const char sname[],const char mname[]) 195 { 196 PetscErrorCode ierr; 197 MatRootName names; 198 199 PetscFunctionBegin; 200 ierr = PetscNew(&names);CHKERRQ(ierr); 201 ierr = PetscStrallocpy(rname,&names->rname);CHKERRQ(ierr); 202 ierr = PetscStrallocpy(sname,&names->sname);CHKERRQ(ierr); 203 ierr = PetscStrallocpy(mname,&names->mname);CHKERRQ(ierr); 204 if (!MatRootNameList) { 205 MatRootNameList = names; 206 } else { 207 MatRootName next = MatRootNameList; 208 while (next->next) next = next->next; 209 next->next = names; 210 } 211 PetscFunctionReturn(0); 212 } 213 214 215 216 217 218 219 220