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