1fe1899a2SJed Brown #include <petscdmshell.h> /*I "petscdmshell.h" I*/ 2*07475bc1SBarry Smith #include <petscmat.h> 3*07475bc1SBarry Smith #include <petsc-private/dmimpl.h> 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; 34ad6bc421SBarry Smith /* the check below is tacky and incomplete */ 35fe1899a2SJed Brown if (mtype) { 36ad6bc421SBarry Smith PetscBool flg,aij,seqaij,mpiaij; 37251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,mtype,&flg);CHKERRQ(ierr); 38ad6bc421SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&seqaij);CHKERRQ(ierr); 39ad6bc421SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&mpiaij);CHKERRQ(ierr); 40ad6bc421SBarry Smith ierr = PetscStrcmp(mtype,MATAIJ,&aij);CHKERRQ(ierr); 41ad6bc421SBarry Smith if (!flg) { 42ad6bc421SBarry Smith if (!(aij & (seqaij || mpiaij))) SETERRQ2(((PetscObject)dm)->comm,PETSC_ERR_ARG_NOTSAMETYPE,"Requested matrix of type %s, but only %s available",mtype,((PetscObject)A)->type_name); 43ad6bc421SBarry Smith } 44fe1899a2SJed Brown } 45fe1899a2SJed Brown if (((PetscObject)A)->refct < 2) { /* We have an exclusive reference so we can give it out */ 46fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 47fe1899a2SJed Brown ierr = MatZeroEntries(A);CHKERRQ(ierr); 48fe1899a2SJed Brown *J = A; 49fe1899a2SJed Brown } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 50fe1899a2SJed Brown ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,J);CHKERRQ(ierr); 51fe1899a2SJed Brown ierr = MatZeroEntries(*J);CHKERRQ(ierr); 52fe1899a2SJed Brown } 53fe1899a2SJed Brown PetscFunctionReturn(0); 54fe1899a2SJed Brown } 55fe1899a2SJed Brown 56fe1899a2SJed Brown #undef __FUNCT__ 57fe1899a2SJed Brown #define __FUNCT__ "DMCreateGlobalVector_Shell" 58fe1899a2SJed Brown PetscErrorCode DMCreateGlobalVector_Shell(DM dm,Vec *gvec) 59fe1899a2SJed Brown { 60fe1899a2SJed Brown PetscErrorCode ierr; 61fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 62fe1899a2SJed Brown Vec X; 63fe1899a2SJed Brown 64fe1899a2SJed Brown PetscFunctionBegin; 65fe1899a2SJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 66fe1899a2SJed Brown PetscValidPointer(gvec,2); 67fe1899a2SJed Brown *gvec = 0; 68fe1899a2SJed Brown X = shell->Xglobal; 698c87107bSJed Brown if (!X) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_USER,"Must call DMShellSetGlobalVector() or DMShellSetCreateGlobalVector()"); 70fe1899a2SJed Brown if (((PetscObject)X)->refct < 2) { /* We have an exclusive reference so we can give it out */ 71fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 72fe1899a2SJed Brown ierr = VecZeroEntries(X);CHKERRQ(ierr); 73fe1899a2SJed Brown *gvec = X; 74fe1899a2SJed Brown } else { /* Need to create a copy, could use MAT_SHARE_NONZERO_PATTERN in most cases */ 75fe1899a2SJed Brown ierr = VecDuplicate(X,gvec);CHKERRQ(ierr); 76fe1899a2SJed Brown ierr = VecZeroEntries(*gvec);CHKERRQ(ierr); 77fe1899a2SJed Brown } 78c688c046SMatthew G Knepley ierr = VecSetDM(*gvec,dm);CHKERRQ(ierr); 79fe1899a2SJed Brown PetscFunctionReturn(0); 80fe1899a2SJed Brown } 81fe1899a2SJed Brown 82fe1899a2SJed Brown #undef __FUNCT__ 83fe1899a2SJed Brown #define __FUNCT__ "DMShellSetMatrix" 84fe1899a2SJed Brown /*@ 85fe1899a2SJed Brown DMShellSetMatrix - sets a template matrix associated with the DMShell 86fe1899a2SJed Brown 87fe1899a2SJed Brown Collective 88fe1899a2SJed Brown 89fe1899a2SJed Brown Input Arguments: 90fe1899a2SJed Brown + dm - shell DM 91fe1899a2SJed Brown - J - template matrix 92fe1899a2SJed Brown 93fe1899a2SJed Brown Level: advanced 94fe1899a2SJed Brown 95fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetCreateMatrix() 96fe1899a2SJed Brown @*/ 97fe1899a2SJed Brown PetscErrorCode DMShellSetMatrix(DM dm,Mat J) 98fe1899a2SJed Brown { 99fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 100fe1899a2SJed Brown PetscErrorCode ierr; 1018c87107bSJed Brown PetscBool isshell; 102fe1899a2SJed Brown 103fe1899a2SJed Brown PetscFunctionBegin; 1048c87107bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1058c87107bSJed Brown PetscValidHeaderSpecific(J,MAT_CLASSID,2); 106251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 1078c87107bSJed Brown if (!isshell) PetscFunctionReturn(0); 108fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)J);CHKERRQ(ierr); 109fe1899a2SJed Brown ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 110fe1899a2SJed Brown shell->A = J; 111fe1899a2SJed Brown PetscFunctionReturn(0); 112fe1899a2SJed Brown } 113fe1899a2SJed Brown 114fe1899a2SJed Brown #undef __FUNCT__ 115fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateMatrix" 116fe1899a2SJed Brown /*@C 117fe1899a2SJed Brown DMShellSetCreateMatrix - sets the routine to create a matrix associated with the shell DM 118fe1899a2SJed Brown 119fe1899a2SJed Brown Logically Collective on DM 120fe1899a2SJed Brown 121fe1899a2SJed Brown Input Arguments: 122fe1899a2SJed Brown + dm - the shell DM 123fe1899a2SJed Brown - func - the function to create a matrix 124fe1899a2SJed Brown 125fe1899a2SJed Brown Level: advanced 126fe1899a2SJed Brown 127fe1899a2SJed Brown .seealso: DMCreateMatrix(), DMShellSetMatrix() 128fe1899a2SJed Brown @*/ 12919fd82e9SBarry Smith PetscErrorCode DMShellSetCreateMatrix(DM dm,PetscErrorCode (*func)(DM,MatType,Mat*)) 130fe1899a2SJed Brown { 131fe1899a2SJed Brown 132fe1899a2SJed Brown PetscFunctionBegin; 133fe1899a2SJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 134fe1899a2SJed Brown dm->ops->creatematrix = func; 135fe1899a2SJed Brown PetscFunctionReturn(0); 136fe1899a2SJed Brown } 137fe1899a2SJed Brown 138fe1899a2SJed Brown #undef __FUNCT__ 139fe1899a2SJed Brown #define __FUNCT__ "DMShellSetGlobalVector" 140fe1899a2SJed Brown /*@ 141fe1899a2SJed Brown DMShellSetGlobalVector - sets a template global vector associated with the DMShell 142fe1899a2SJed Brown 143fe1899a2SJed Brown Logically Collective on DM 144fe1899a2SJed Brown 145fe1899a2SJed Brown Input Arguments: 146fe1899a2SJed Brown + dm - shell DM 147fe1899a2SJed Brown - X - template vector 148fe1899a2SJed Brown 149fe1899a2SJed Brown Level: advanced 150fe1899a2SJed Brown 151fe1899a2SJed Brown .seealso: DMCreateGlobalVector(), DMShellSetMatrix(), DMShellSetCreateGlobalVector() 152fe1899a2SJed Brown @*/ 153fe1899a2SJed Brown PetscErrorCode DMShellSetGlobalVector(DM dm,Vec X) 154fe1899a2SJed Brown { 155fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 156fe1899a2SJed Brown PetscErrorCode ierr; 1578c87107bSJed Brown PetscBool isshell; 158fe1899a2SJed Brown 159fe1899a2SJed Brown PetscFunctionBegin; 1608c87107bSJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1618c87107bSJed Brown PetscValidHeaderSpecific(X,VEC_CLASSID,2); 162251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)dm,DMSHELL,&isshell);CHKERRQ(ierr); 1638c87107bSJed Brown if (!isshell) PetscFunctionReturn(0); 164fe1899a2SJed Brown ierr = PetscObjectReference((PetscObject)X);CHKERRQ(ierr); 165fe1899a2SJed Brown ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 166fe1899a2SJed Brown shell->Xglobal = X; 167fe1899a2SJed Brown PetscFunctionReturn(0); 168fe1899a2SJed Brown } 169fe1899a2SJed Brown 170fe1899a2SJed Brown #undef __FUNCT__ 171fe1899a2SJed Brown #define __FUNCT__ "DMShellSetCreateGlobalVector" 172fe1899a2SJed Brown /*@C 173fe1899a2SJed Brown DMShellSetCreateGlobalVector - sets the routine to create a global vector associated with the shell DM 174fe1899a2SJed Brown 175fe1899a2SJed Brown Logically Collective 176fe1899a2SJed Brown 177fe1899a2SJed Brown Input Arguments: 178fe1899a2SJed Brown + dm - the shell DM 179fe1899a2SJed Brown - func - the creation routine 180fe1899a2SJed Brown 181fe1899a2SJed Brown Level: advanced 182fe1899a2SJed Brown 183fe1899a2SJed Brown .seealso: DMShellSetGlobalVector(), DMShellSetCreateMatrix() 184fe1899a2SJed Brown @*/ 185fe1899a2SJed Brown PetscErrorCode DMShellSetCreateGlobalVector(DM dm,PetscErrorCode (*func)(DM,Vec*)) 186fe1899a2SJed Brown { 187fe1899a2SJed Brown 188fe1899a2SJed Brown PetscFunctionBegin; 189fe1899a2SJed Brown PetscValidHeaderSpecific(dm,DM_CLASSID,1); 190fe1899a2SJed Brown dm->ops->createglobalvector = func; 191fe1899a2SJed Brown PetscFunctionReturn(0); 192fe1899a2SJed Brown } 193fe1899a2SJed Brown 194fe1899a2SJed Brown #undef __FUNCT__ 195fe1899a2SJed Brown #define __FUNCT__ "DMDestroy_Shell" 196fe1899a2SJed Brown static PetscErrorCode DMDestroy_Shell(DM dm) 197fe1899a2SJed Brown { 198fe1899a2SJed Brown PetscErrorCode ierr; 199fe1899a2SJed Brown DM_Shell *shell = (DM_Shell*)dm->data; 200fe1899a2SJed Brown 201fe1899a2SJed Brown PetscFunctionBegin; 202fe1899a2SJed Brown ierr = MatDestroy(&shell->A);CHKERRQ(ierr); 203fe1899a2SJed Brown ierr = VecDestroy(&shell->Xglobal);CHKERRQ(ierr); 2047b6ad80cSMatthew G Knepley /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 2057b6ad80cSMatthew G Knepley ierr = PetscFree(shell);CHKERRQ(ierr); 206fe1899a2SJed Brown PetscFunctionReturn(0); 207fe1899a2SJed Brown } 208fe1899a2SJed Brown 2092d53ad75SBarry Smith #undef __FUNCT__ 2102d53ad75SBarry Smith #define __FUNCT__ "DMView_Shell" 2112d53ad75SBarry Smith static PetscErrorCode DMView_Shell(DM dm,PetscViewer v) 2122d53ad75SBarry Smith { 2132d53ad75SBarry Smith PetscErrorCode ierr; 2142d53ad75SBarry Smith DM_Shell *shell = (DM_Shell*)dm->data; 2152d53ad75SBarry Smith 2162d53ad75SBarry Smith PetscFunctionBegin; 2172d53ad75SBarry Smith ierr = VecView(shell->Xglobal,v);CHKERRQ(ierr); 2182d53ad75SBarry Smith PetscFunctionReturn(0); 2192d53ad75SBarry Smith } 2202d53ad75SBarry Smith 2212d53ad75SBarry Smith #undef __FUNCT__ 2222d53ad75SBarry Smith #define __FUNCT__ "DMLoad_Shell" 2232d53ad75SBarry Smith static PetscErrorCode DMLoad_Shell(DM dm,PetscViewer v) 2242d53ad75SBarry Smith { 2252d53ad75SBarry Smith PetscErrorCode ierr; 2262d53ad75SBarry Smith DM_Shell *shell = (DM_Shell*)dm->data; 2272d53ad75SBarry Smith 2282d53ad75SBarry Smith PetscFunctionBegin; 2292d53ad75SBarry Smith ierr = VecCreate(((PetscObject)dm)->comm,&shell->Xglobal);CHKERRQ(ierr); 2302d53ad75SBarry Smith ierr = VecLoad(shell->Xglobal,v);CHKERRQ(ierr); 2312d53ad75SBarry Smith PetscFunctionReturn(0); 2322d53ad75SBarry Smith } 233fe1899a2SJed Brown 234fe1899a2SJed Brown #undef __FUNCT__ 235fe1899a2SJed Brown #define __FUNCT__ "DMCreate_Shell" 2368c87107bSJed Brown PETSC_EXTERN_C PetscErrorCode DMCreate_Shell(DM dm) 237fe1899a2SJed Brown { 238fe1899a2SJed Brown PetscErrorCode ierr; 239fe1899a2SJed Brown DM_Shell *shell; 240fe1899a2SJed Brown 241fe1899a2SJed Brown PetscFunctionBegin; 2428c87107bSJed Brown ierr = PetscNewLog(dm,DM_Shell,&shell);CHKERRQ(ierr); 2438c87107bSJed Brown dm->data = shell; 244fe1899a2SJed Brown 2458c87107bSJed Brown ierr = PetscObjectChangeTypeName((PetscObject)dm,DMSHELL);CHKERRQ(ierr); 2468c87107bSJed Brown dm->ops->destroy = DMDestroy_Shell; 2478c87107bSJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Shell; 2488c87107bSJed Brown dm->ops->creatematrix = DMCreateMatrix_Shell; 2492d53ad75SBarry Smith dm->ops->view = DMView_Shell; 2502d53ad75SBarry Smith dm->ops->load = DMLoad_Shell; 251fe1899a2SJed Brown PetscFunctionReturn(0); 252fe1899a2SJed Brown } 253fe1899a2SJed Brown 254fe1899a2SJed Brown #undef __FUNCT__ 255fe1899a2SJed Brown #define __FUNCT__ "DMShellCreate" 256fe1899a2SJed Brown /*@ 257fe1899a2SJed Brown DMShellCreate - Creates a shell DM object, used to manage user-defined problem data 258fe1899a2SJed Brown 259fe1899a2SJed Brown Collective on MPI_Comm 260fe1899a2SJed Brown 261fe1899a2SJed Brown Input Parameter: 262fe1899a2SJed Brown . comm - the processors that will share the global vector 263fe1899a2SJed Brown 264fe1899a2SJed Brown Output Parameters: 265fe1899a2SJed Brown . shell - the shell DM 266fe1899a2SJed Brown 267fe1899a2SJed Brown Level: advanced 268fe1899a2SJed Brown 269fe1899a2SJed Brown .seealso DMDestroy(), DMCreateGlobalVector() 270fe1899a2SJed Brown @*/ 271fe1899a2SJed Brown PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm) 272fe1899a2SJed Brown { 273fe1899a2SJed Brown PetscErrorCode ierr; 274fe1899a2SJed Brown 275fe1899a2SJed Brown PetscFunctionBegin; 276fe1899a2SJed Brown PetscValidPointer(dm,2); 277fe1899a2SJed Brown ierr = DMCreate(comm,dm);CHKERRQ(ierr); 278fe1899a2SJed Brown ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr); 279fe1899a2SJed Brown PetscFunctionReturn(0); 280fe1899a2SJed Brown } 281