1 #include <petscdmshell.h> /*I "petscdmshell.h" I*/ 2 #include <petscmat.h> /*I "petscmat.h" I*/ 3 #include <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 = PetscTypeCompare((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 (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */ 53 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 54 ierr = VecZeroEntries(X);CHKERRQ(ierr); 55 *gvec = X; 56 } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 57 ierr = VecDuplicate(X,gvec);CHKERRQ(ierr); 58 ierr = VecZeroEntries(*gvec);CHKERRQ(ierr); 59 } 60 ierr = PetscObjectCompose((PetscObject)*gvec,"DM",(PetscObject)dm);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "DMShellSetMatrix" 66 /*@ 67 DMShellSetMatrix - sets a template matrix associated with the DMShell 68 69 Collective 70 71 Input Arguments: 72 + dm - shell DM 73 - J - template matrix 74 75 Level: advanced 76 77 .seealso: DMCreateMatrix(), DMShellSetCreateMatrix() 78 @*/ 79 PetscErrorCode DMShellSetMatrix(DM dm,Mat J) 80 { 81 DM_Shell *shell = (DM_Shell*)dm->data; 82 PetscErrorCode ierr; 83 84 PetscFunctionBegin; 85 ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 86 ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 87 shell->A = J; 88 PetscFunctionReturn(0); 89 } 90 91 #undef __FUNCT__ 92 #define __FUNCT__ "DMShellSetCreateMatrix" 93 /*@C 94 DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM 95 96 Logically Collective on DM 97 98 Input Arguments: 99 + dm - the shell DM 100 - func - the function to create a matrix 101 102 Level: advanced 103 104 .seealso: DMCreateMatrix(), DMShellSetMatrix() 105 @*/ 106 PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,const MatType,Mat*)) 107 { 108 109 PetscFunctionBegin; 110 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 111 dm->ops->creatematrix = func; 112 PetscFunctionReturn(0); 113 } 114 115 #undef __FUNCT__ 116 #define __FUNCT__ "DMShellSetGlobalVector" 117 /*@ 118 DMShellSetGlobalVector - sets a template global vector associated with the DMShell 119 120 Logically Collective on DM 121 122 Input Arguments: 123 + dm - shell DM 124 - X - template vector 125 126 Level: advanced 127 128 .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector() 129 @*/ 130 PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X) 131 { 132 DM_Shell *shell = (DM_Shell*)dm->data; 133 PetscErrorCode ierr; 134 135 PetscFunctionBegin; 136 ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 137 ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 138 shell->Xglobal = X; 139 PetscFunctionReturn(0); 140 } 141 142 #undef __FUNCT__ 143 #define __FUNCT__ "DMShellSetCreateGlobalVector" 144 /*@C 145 DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM 146 147 Logically Collective 148 149 Input Arguments: 150 + dm - the shell DM 151 - func - the creation routine 152 153 Level: advanced 154 155 .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix() 156 @*/ 157 PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*)) 158 { 159 160 PetscFunctionBegin; 161 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 162 dm->ops->createglobalvector = func; 163 PetscFunctionReturn(0); 164 } 165 166 #undef __FUNCT__ 167 #define __FUNCT__ "DMDestroy_Shell" 168 static PetscErrorCode DMDestroy_Shell(DM dm) 169 { 170 PetscErrorCode ierr; 171 DM_Shell *shell = (DM_Shell*)dm->data; 172 173 PetscFunctionBegin; 174 ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 175 ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 176 ierr = PetscFree(dm->data);CHKERRQ(ierr); 177 PetscFunctionReturn(0); 178 } 179 180 181 #undef __FUNCT__ 182 #define __FUNCT__ "DMCreate_Shell" 183 PETSC_EXTERN_C PetscErrorCode DMCreate_Shell(DM p) 184 { 185 PetscErrorCode ierr; 186 DM_Shell *shell; 187 188 PetscFunctionBegin; 189 ierr = PetscNewLog(p,DM_Shell,&shell);CHKERRQ(ierr); 190 p->data = shell; 191 192 ierr = PetscObjectChangeTypeName((PetscObject)p,DMSHELL);CHKERRQ(ierr); 193 p->ops->createglobalvector = DMCreateGlobalVector_Shell; 194 p->ops->creatematrix = DMCreateMatrix_Shell; 195 p->ops->destroy = DMDestroy_Shell; 196 PetscFunctionReturn(0); 197 } 198 199 #undef __FUNCT__ 200 #define __FUNCT__ "DMShellCreate" 201 /*@ 202 DMShellCreate - Creates a shell DM object, used to manage user-defined problem data 203 204 Collective on MPI_Comm 205 206 Input Parameter: 207 . comm - the processors that will share the global vector 208 209 Output Parameters: 210 . shell - the shell DM 211 212 Level: advanced 213 214 .seealso DMDestroy(), DMCreateGlobalVector() 215 @*/ 216 PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm) 217 { 218 PetscErrorCode ierr; 219 220 PetscFunctionBegin; 221 PetscValidPointer(dm,2); 222 ierr = DMCreate(comm,dm);CHKERRQ(ierr); 223 ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr); 224 PetscFunctionReturn(0); 225 } 226