1fe1899a2SJed Brown #include <petscdmshell.h> /*I "petscdmshell.h" I*/ 2fe1899a2SJed Brown #include <petscmat.h> /*I "petscmat.h" I*/ 3b45d2f2cSJed 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" 1219fd82e9SBarry Smith static PetscErrorCode DMCreateMatrix_Shell(DM dm,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); 217bde9f88SJed Brown if (!shell->A) { 227bde9f88SJed Brown if (shell->Xglobal) { 237bde9f88SJed Brown PetscInt m,M; 247bde9f88SJed Brown ierr = PetscInfo(dm,"Naively creating matrix using global vector distribution without preallocation");CHKERRQ(ierr); 257bde9f88SJed Brown ierr = VecGetSize(shell->Xglobal,&M);CHKERRQ(ierr); 267bde9f88SJed Brown ierr = VecGetLocalSize(shell->Xglobal,&m);CHKERRQ(ierr); 277bde9f88SJed Brown ierr = MatCreate(((PetscObject)dm)->comm,&shell->A);CHKERRQ(ierr); 287bde9f88SJed Brown ierr = MatSetSizes(shell->A,m,m,M,M);CHKERRQ(ierr); 297bde9f88SJed Brown if (mtype) {ierr = MatSetType(shell->A,mtype);CHKERRQ(ierr);} 307bde9f88SJed Brown ierr = MatSetUp(shell->A);CHKERRQ(ierr); 317bde9f88SJed Brown } else SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetMatrix(), DMShellSetCreateMatrix(), or provide a vector"); 327bde9f88SJed Brown } 33fe1899a2SJed Brown A = shell->A; 34fe1899a2SJed Brown if (mtype) { 35fe1899a2SJed Brown PetscBool flg; 36251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr); 37fe1899a2SJed 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); 38fe1899a2SJed Brown } 39fe1899a2SJed Brown if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */ 40fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 41fe1899a2SJed Brown ierr = MatZeroEntries(A);CHKERRQ(ierr); 42fe1899a2SJed Brown *J = A; 43fe1899a2SJed Brown } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 44fe1899a2SJed Brown ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr); 45fe1899a2SJed Brown ierr = MatZeroEntries(*J);CHKERRQ(ierr); 46fe1899a2SJed Brown } 47fe1899a2SJed Brown PetscFunctionReturn(0); 48fe1899a2SJed Brown } 49fe1899a2SJed Brown 50fe1899a2SJed Brown #undef __FUNCT__ 51fe1899a2SJed Brown #define __FUNCT__ "DMCreateGlobalVector_Shell" 52fe1899a2SJed Brown PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec) 53fe1899a2SJed Brown { 54fe1899a2SJed Brown PetscErrorCode ierr; 55fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 56fe1899a2SJed Brown Vec X; 57fe1899a2SJed Brown 58fe1899a2SJed Brown PetscFunctionBegin; 59fe1899a2SJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 60fe1899a2SJed Brown PetscValidPointer(gvec,2); 61fe1899a2SJed Brown *gvec = 0; 62fe1899a2SJed Brown X = shell->Xglobal; 638c87107bSJed Brown if (!X) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()"); 64fe1899a2SJed Brown if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */ 65fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 66fe1899a2SJed Brown ierr = VecZeroEntries(X);CHKERRQ(ierr); 67fe1899a2SJed Brown *gvec = X; 68fe1899a2SJed Brown } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 69fe1899a2SJed Brown ierr = VecDuplicate(X,gvec);CHKERRQ(ierr); 70fe1899a2SJed Brown ierr = VecZeroEntries(*gvec);CHKERRQ(ierr); 71fe1899a2SJed Brown } 72*c688c046SMatthew G Knepley ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr); 73fe1899a2SJed Brown PetscFunctionReturn(0); 74fe1899a2SJed Brown } 75fe1899a2SJed Brown 76fe1899a2SJed Brown #undef __FUNCT__ 77fe1899a2SJed Brown #define __FUNCT__ "DMShellSetMatrix" 78fe1899a2SJed Brown /*@ 79fe1899a2SJed Brown DMShellSetMatrix - sets a template matrix associated with the DMShell 80fe1899a2SJed Brown 81fe1899a2SJed Brown Collective 82fe1899a2SJed Brown 83fe1899a2SJed Brown Input Arguments: 84fe1899a2SJed Brown + dm - shell DM 85fe1899a2SJed Brown - J - template matrix 86fe1899a2SJed Brown 87fe1899a2SJed Brown Level: advanced 88fe1899a2SJed Brown 89fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetCreateMatrix() 90fe1899a2SJed Brown @*/ 91fe1899a2SJed Brown PetscErrorCode DMShellSetMatrix(DM dm,Mat J) 92fe1899a2SJed Brown { 93fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 94fe1899a2SJed Brown PetscErrorCode ierr; 958c87107bSJed Brown PetscBool isshell; 96fe1899a2SJed Brown 97fe1899a2SJed Brown PetscFunctionBegin; 988c87107bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 998c87107bSJed Brown PetscValidHeaderSpecific(J,MAT_CLASSID,2); 100251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 1018c87107bSJed Brown if (!isshell) PetscFunctionReturn(0); 102fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 103fe1899a2SJed Brown ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 104fe1899a2SJed Brown shell->A = J; 105fe1899a2SJed Brown PetscFunctionReturn(0); 106fe1899a2SJed Brown } 107fe1899a2SJed Brown 108fe1899a2SJed Brown #undef __FUNCT__ 109fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateMatrix" 110fe1899a2SJed Brown /*@C 111fe1899a2SJed Brown DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM 112fe1899a2SJed Brown 113fe1899a2SJed Brown Logically Collective on DM 114fe1899a2SJed Brown 115fe1899a2SJed Brown Input Arguments: 116fe1899a2SJed Brown + dm - the shell DM 117fe1899a2SJed Brown - func - the function to create a matrix 118fe1899a2SJed Brown 119fe1899a2SJed Brown Level: advanced 120fe1899a2SJed Brown 121fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetMatrix() 122fe1899a2SJed Brown @*/ 12319fd82e9SBarry Smith PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,MatType,Mat*)) 124fe1899a2SJed Brown { 125fe1899a2SJed Brown 126fe1899a2SJed Brown PetscFunctionBegin; 127fe1899a2SJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 128fe1899a2SJed Brown dm->ops->creatematrix = func; 129fe1899a2SJed Brown PetscFunctionReturn(0); 130fe1899a2SJed Brown } 131fe1899a2SJed Brown 132fe1899a2SJed Brown #undef __FUNCT__ 133fe1899a2SJed Brown #define __FUNCT__ "DMShellSetGlobalVector" 134fe1899a2SJed Brown /*@ 135fe1899a2SJed Brown DMShellSetGlobalVector - sets a template global vector associated with the DMShell 136fe1899a2SJed Brown 137fe1899a2SJed Brown Logically Collective on DM 138fe1899a2SJed Brown 139fe1899a2SJed Brown Input Arguments: 140fe1899a2SJed Brown + dm - shell DM 141fe1899a2SJed Brown - X - template vector 142fe1899a2SJed Brown 143fe1899a2SJed Brown Level: advanced 144fe1899a2SJed Brown 145fe1899a2SJed Brown .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector() 146fe1899a2SJed Brown @*/ 147fe1899a2SJed Brown PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X) 148fe1899a2SJed Brown { 149fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 150fe1899a2SJed Brown PetscErrorCode ierr; 1518c87107bSJed Brown PetscBool isshell; 152fe1899a2SJed Brown 153fe1899a2SJed Brown PetscFunctionBegin; 1548c87107bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1558c87107bSJed Brown PetscValidHeaderSpecific(X,VEC_CLASSID,2); 156251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 1578c87107bSJed Brown if (!isshell) PetscFunctionReturn(0); 158fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 159fe1899a2SJed Brown ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 160fe1899a2SJed Brown shell->Xglobal = X; 161fe1899a2SJed Brown PetscFunctionReturn(0); 162fe1899a2SJed Brown } 163fe1899a2SJed Brown 164fe1899a2SJed Brown #undef __FUNCT__ 165fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateGlobalVector" 166fe1899a2SJed Brown /*@C 167fe1899a2SJed Brown DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM 168fe1899a2SJed Brown 169fe1899a2SJed Brown Logically Collective 170fe1899a2SJed Brown 171fe1899a2SJed Brown Input Arguments: 172fe1899a2SJed Brown + dm - the shell DM 173fe1899a2SJed Brown - func - the creation routine 174fe1899a2SJed Brown 175fe1899a2SJed Brown Level: advanced 176fe1899a2SJed Brown 177fe1899a2SJed Brown .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix() 178fe1899a2SJed Brown @*/ 179fe1899a2SJed Brown PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*)) 180fe1899a2SJed Brown { 181fe1899a2SJed Brown 182fe1899a2SJed Brown PetscFunctionBegin; 183fe1899a2SJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 184fe1899a2SJed Brown dm->ops->createglobalvector = func; 185fe1899a2SJed Brown PetscFunctionReturn(0); 186fe1899a2SJed Brown } 187fe1899a2SJed Brown 188fe1899a2SJed Brown #undef __FUNCT__ 189fe1899a2SJed Brown #define __FUNCT__ "DMDestroy_Shell" 190fe1899a2SJed Brown static PetscErrorCode DMDestroy_Shell(DM dm) 191fe1899a2SJed Brown { 192fe1899a2SJed Brown PetscErrorCode ierr; 193fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 194fe1899a2SJed Brown 195fe1899a2SJed Brown PetscFunctionBegin; 196fe1899a2SJed Brown ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 197fe1899a2SJed Brown ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 1987b6ad80cSMatthew G Knepley /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 1997b6ad80cSMatthew G Knepley ierr = PetscFree(shell);CHKERRQ(ierr); 200fe1899a2SJed Brown PetscFunctionReturn(0); 201fe1899a2SJed Brown } 202fe1899a2SJed Brown 203fe1899a2SJed Brown 204fe1899a2SJed Brown #undef __FUNCT__ 205fe1899a2SJed Brown #define __FUNCT__ "DMCreate_Shell" 2068c87107bSJed Brown PETSC_EXTERN_C PetscErrorCode DMCreate_Shell(DM dm) 207fe1899a2SJed Brown { 208fe1899a2SJed Brown PetscErrorCode ierr; 209fe1899a2SJed Brown DM_Shell *shell; 210fe1899a2SJed Brown 211fe1899a2SJed Brown PetscFunctionBegin; 2128c87107bSJed Brown ierr = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr); 2138c87107bSJed Brown dm->data = shell; 214fe1899a2SJed Brown 2158c87107bSJed Brown ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr); 2168c87107bSJed Brown dm->ops->destroy = DMDestroy_Shell; 2178c87107bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Shell; 2188c87107bSJed Brown dm->ops->creatematrix = DMCreateMatrix_Shell; 219fe1899a2SJed Brown PetscFunctionReturn(0); 220fe1899a2SJed Brown } 221fe1899a2SJed Brown 222fe1899a2SJed Brown #undef __FUNCT__ 223fe1899a2SJed Brown #define __FUNCT__ "DMShellCreate" 224fe1899a2SJed Brown /*@ 225fe1899a2SJed Brown DMShellCreate - Creates a shell DM object, used to manage user-defined problem data 226fe1899a2SJed Brown 227fe1899a2SJed Brown Collective on MPI_Comm 228fe1899a2SJed Brown 229fe1899a2SJed Brown Input Parameter: 230fe1899a2SJed Brown . comm - the processors that will share the global vector 231fe1899a2SJed Brown 232fe1899a2SJed Brown Output Parameters: 233fe1899a2SJed Brown . shell - the shell DM 234fe1899a2SJed Brown 235fe1899a2SJed Brown Level: advanced 236fe1899a2SJed Brown 237fe1899a2SJed Brown .seealso DMDestroy(), DMCreateGlobalVector() 238fe1899a2SJed Brown @*/ 239fe1899a2SJed Brown PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm) 240fe1899a2SJed Brown { 241fe1899a2SJed Brown PetscErrorCode ierr; 242fe1899a2SJed Brown 243fe1899a2SJed Brown PetscFunctionBegin; 244fe1899a2SJed Brown PetscValidPointer(dm,2); 245fe1899a2SJed Brown ierr = DMCreate(comm,dm);CHKERRQ(ierr); 246fe1899a2SJed Brown ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr); 247fe1899a2SJed Brown PetscFunctionReturn(0); 248fe1899a2SJed Brown } 249