1 #include <petscdmshell.h> /*I "petscdmshell.h" I*/ 2 #include <petscmat.h> /*I "petscmat.h" I*/ 3 #include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/ 4 5 typedef struct { 6 Vec Xglobal; 7 Mat A; 8 } DM_Shell; 9 10 #undef __FUNCT__ 11 #define __FUNCT__ "DMCreateMatrix_Shell" 12 static PetscErrorCode DMCreateMatrix_Shell(DM dm,const MatType mtype,Mat *J) 13 { 14 PetscErrorCode ierr; 15 DM_Shell *shell = (DM_Shell*)dm->data; 16 Mat A; 17 18 PetscFunctionBegin; 19 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 20 PetscValidPointer(J,3); 21 A = shell->A; 22 if (!A) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetMatrix() or DMShellSetCreateMatrix()"); 23 if (mtype) { 24 PetscBool flg; 25 ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr); 26 if (!flg) SETERRQ2(((PetscObject)dm)->comm,PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",mtype,((PetscObject)A)->type_name); 27 } 28 if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */ 29 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 30 ierr = MatZeroEntries(A);CHKERRQ(ierr); 31 *J = A; 32 } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 33 ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr); 34 ierr = MatZeroEntries(*J);CHKERRQ(ierr); 35 } 36 PetscFunctionReturn(0); 37 } 38 39 #undef __FUNCT__ 40 #define __FUNCT__ "DMCreateGlobalVector_Shell" 41 PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec) 42 { 43 PetscErrorCode ierr; 44 DM_Shell *shell = (DM_Shell*)dm->data; 45 Vec X; 46 47 PetscFunctionBegin; 48 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 49 PetscValidPointer(gvec,2); 50 *gvec = 0; 51 X = shell->Xglobal; 52 if (!X) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()"); 53 if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */ 54 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 55 ierr = VecZeroEntries(X);CHKERRQ(ierr); 56 *gvec = X; 57 } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 58 ierr = VecDuplicate(X,gvec);CHKERRQ(ierr); 59 ierr = VecZeroEntries(*gvec);CHKERRQ(ierr); 60 } 61 ierr = PetscObjectCompose((PetscObject)*gvec,"DM",(PetscObject)dm);CHKERRQ(ierr); 62 PetscFunctionReturn(0); 63 } 64 65 #undef __FUNCT__ 66 #define __FUNCT__ "DMShellSetMatrix" 67 /*@ 68 DMShellSetMatrix - sets a template matrix associated with the DMShell 69 70 Collective 71 72 Input Arguments: 73 + dm - shell DM 74 - J - template matrix 75 76 Level: advanced 77 78 .seealso: DMCreateMatrix(), DMShellSetCreateMatrix() 79 @*/ 80 PetscErrorCode DMShellSetMatrix(DM dm,Mat J) 81 { 82 DM_Shell *shell = (DM_Shell*)dm->data; 83 PetscErrorCode ierr; 84 PetscBool isshell; 85 86 PetscFunctionBegin; 87 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 88 PetscValidHeaderSpecific(J,MAT_CLASSID,2); 89 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 90 if (!isshell) PetscFunctionReturn(0); 91 ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 92 ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 93 shell->A = J; 94 PetscFunctionReturn(0); 95 } 96 97 #undef __FUNCT__ 98 #define __FUNCT__ "DMShellSetCreateMatrix" 99 /*@C 100 DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM 101 102 Logically Collective on DM 103 104 Input Arguments: 105 + dm - the shell DM 106 - func - the function to create a matrix 107 108 Level: advanced 109 110 .seealso: DMCreateMatrix(), DMShellSetMatrix() 111 @*/ 112 PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,const MatType,Mat*)) 113 { 114 115 PetscFunctionBegin; 116 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 117 dm->ops->creatematrix = func; 118 PetscFunctionReturn(0); 119 } 120 121 #undef __FUNCT__ 122 #define __FUNCT__ "DMShellSetGlobalVector" 123 /*@ 124 DMShellSetGlobalVector - sets a template global vector associated with the DMShell 125 126 Logically Collective on DM 127 128 Input Arguments: 129 + dm - shell DM 130 - X - template vector 131 132 Level: advanced 133 134 .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector() 135 @*/ 136 PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X) 137 { 138 DM_Shell *shell = (DM_Shell*)dm->data; 139 PetscErrorCode ierr; 140 PetscBool isshell; 141 142 PetscFunctionBegin; 143 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 144 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 145 ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 146 if (!isshell) PetscFunctionReturn(0); 147 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 148 ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 149 shell->Xglobal = X; 150 PetscFunctionReturn(0); 151 } 152 153 #undef __FUNCT__ 154 #define __FUNCT__ "DMShellSetCreateGlobalVector" 155 /*@C 156 DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM 157 158 Logically Collective 159 160 Input Arguments: 161 + dm - the shell DM 162 - func - the creation routine 163 164 Level: advanced 165 166 .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix() 167 @*/ 168 PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*)) 169 { 170 171 PetscFunctionBegin; 172 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 173 dm->ops->createglobalvector = func; 174 PetscFunctionReturn(0); 175 } 176 177 #undef __FUNCT__ 178 #define __FUNCT__ "DMDestroy_Shell" 179 static PetscErrorCode DMDestroy_Shell(DM dm) 180 { 181 PetscErrorCode ierr; 182 DM_Shell *shell = (DM_Shell*)dm->data; 183 184 PetscFunctionBegin; 185 ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 186 ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 187 ierr = PetscFree(dm->data);CHKERRQ(ierr); 188 PetscFunctionReturn(0); 189 } 190 191 192 #undef __FUNCT__ 193 #define __FUNCT__ "DMCreate_Shell" 194 PETSC_EXTERN_C PetscErrorCode DMCreate_Shell(DM dm) 195 { 196 PetscErrorCode ierr; 197 DM_Shell *shell; 198 199 PetscFunctionBegin; 200 ierr = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr); 201 dm->data = shell; 202 203 ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr); 204 dm->ops->destroy = DMDestroy_Shell; 205 dm->ops->createglobalvector = DMCreateGlobalVector_Shell; 206 dm->ops->creatematrix = DMCreateMatrix_Shell; 207 PetscFunctionReturn(0); 208 } 209 210 #undef __FUNCT__ 211 #define __FUNCT__ "DMShellCreate" 212 /*@ 213 DMShellCreate - Creates a shell DM object, used to manage user-defined problem data 214 215 Collective on MPI_Comm 216 217 Input Parameter: 218 . comm - the processors that will share the global vector 219 220 Output Parameters: 221 . shell - the shell DM 222 223 Level: advanced 224 225 .seealso DMDestroy(), DMCreateGlobalVector() 226 @*/ 227 PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm) 228 { 229 PetscErrorCode ierr; 230 231 PetscFunctionBegin; 232 PetscValidPointer(dm,2); 233 ierr = DMCreate(comm,dm);CHKERRQ(ierr); 234 ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr); 235 PetscFunctionReturn(0); 236 } 237