1c4762a1bSJed Brown 2c4762a1bSJed Brown static char help[] = "\n\n"; 3c4762a1bSJed Brown 4c4762a1bSJed Brown /* 5c4762a1bSJed Brown Demonstrates using DM_BOUNDARY_GHOSTED how to handle a rotated boundary conditions where one edge 6c4762a1bSJed Brown is connected to its immediate neighbor 7c4762a1bSJed Brown 8c4762a1bSJed Brown Consider the domain (with natural numbering) 9c4762a1bSJed Brown 10c4762a1bSJed Brown 6 7 8 11c4762a1bSJed Brown 3 4 5 12c4762a1bSJed Brown 0 1 2 13c4762a1bSJed Brown 14c4762a1bSJed Brown The ghost points along the bottom (directly below the three columns above) should be 0 3 and 6 15c4762a1bSJed Brown while the ghost points along the left side should be 0 1 2 16c4762a1bSJed Brown 17c4762a1bSJed Brown Note that the ghosted local vectors extend in both the x and y directions so, for example if we have a 18c4762a1bSJed Brown single MPI process the ghosted vector has (in the original natural numbering) 19c4762a1bSJed Brown 20c4762a1bSJed Brown x x x x x 21c4762a1bSJed Brown 2 6 7 8 x 22c4762a1bSJed Brown 1 3 4 5 x 23c4762a1bSJed Brown 0 0 1 2 x 24c4762a1bSJed Brown x 0 3 6 x 25c4762a1bSJed Brown 26c4762a1bSJed Brown where x indicates a location that is not updated by the communication and should be used. 27c4762a1bSJed Brown 28c4762a1bSJed Brown For this to make sense the number of grid points in the x and y directions must be the same 29c4762a1bSJed Brown 30c4762a1bSJed Brown This ghost point mapping was suggested by: Wenbo Zhao <zhaowenbo.npic@gmail.com> 31c4762a1bSJed Brown */ 32c4762a1bSJed Brown 33c4762a1bSJed Brown #include <petscdm.h> 34c4762a1bSJed Brown #include <petscdmda.h> 35c4762a1bSJed Brown 36c4762a1bSJed Brown int main(int argc,char **argv) 37c4762a1bSJed Brown { 38c4762a1bSJed Brown PetscInt M = 6; 39c4762a1bSJed Brown DM da; 40c4762a1bSJed Brown Vec local,global,natural; 41c4762a1bSJed Brown PetscInt i,start,end,*ifrom,x,y,xm,ym; 42c4762a1bSJed Brown PetscScalar *xnatural; 43c4762a1bSJed Brown IS from,to; 44c4762a1bSJed Brown AO ao; 45c4762a1bSJed Brown VecScatter scatter1,scatter2; 46c4762a1bSJed Brown PetscViewer subviewer; 47c4762a1bSJed Brown 48*327415f7SBarry Smith PetscFunctionBeginUser; 499566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc,&argv,(char*)0,help)); 50c4762a1bSJed Brown 51c4762a1bSJed Brown /* Create distributed array and get vectors */ 529566063dSJacob Faibussowitsch PetscCall(DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_GHOSTED,DM_BOUNDARY_GHOSTED,DMDA_STENCIL_STAR,M,M,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da)); 539566063dSJacob Faibussowitsch PetscCall(DMSetUp(da)); 549566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(da,&global)); 559566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(da,&local)); 56c4762a1bSJed Brown 57c4762a1bSJed Brown /* construct global to local scatter for the left side of the domain to the ghost on the bottom */ 589566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da,&x,&y,NULL,&xm,&ym,NULL)); 59c4762a1bSJed Brown if (!y) { /* only processes on the bottom of the domain fill up the ghost locations */ 609566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,xm,1,1,&to)); 61c4762a1bSJed Brown } else { 629566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,0,0,0,&to)); 63c4762a1bSJed Brown } 649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xm,&ifrom)); 65c4762a1bSJed Brown for (i=x;i<x+xm;i++) { 66c4762a1bSJed Brown ifrom[i-x] = M*i; 67c4762a1bSJed Brown } 689566063dSJacob Faibussowitsch PetscCall(DMDAGetAO(da,&ao)); 699566063dSJacob Faibussowitsch PetscCall(AOApplicationToPetsc(ao,xm,ifrom)); 70c4762a1bSJed Brown if (!y) { 719566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,xm,ifrom,PETSC_OWN_POINTER,&from)); 72c4762a1bSJed Brown } else { 739566063dSJacob Faibussowitsch PetscCall(PetscFree(ifrom)); 749566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,0,NULL,PETSC_COPY_VALUES,&from)); 75c4762a1bSJed Brown } 769566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(global,from,local,to,&scatter1)); 779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 79c4762a1bSJed Brown 80c4762a1bSJed Brown /* construct global to local scatter for the bottom side of the domain to the ghost on the right */ 81c4762a1bSJed Brown if (!x) { /* only processes on the left side of the domain fill up the ghost locations */ 829566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,ym,xm+2,xm+2,&to)); 83c4762a1bSJed Brown } else { 849566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF,0,0,0,&to)); 85c4762a1bSJed Brown } 869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ym,&ifrom)); 87c4762a1bSJed Brown for (i=y;i<y+ym;i++) { 88c4762a1bSJed Brown ifrom[i-y] = i; 89c4762a1bSJed Brown } 909566063dSJacob Faibussowitsch PetscCall(DMDAGetAO(da,&ao)); 919566063dSJacob Faibussowitsch PetscCall(AOApplicationToPetsc(ao,ym,ifrom)); 92c4762a1bSJed Brown if (!x) { 939566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,ym,ifrom,PETSC_OWN_POINTER,&from)); 94c4762a1bSJed Brown } else { 959566063dSJacob Faibussowitsch PetscCall(PetscFree(ifrom)); 969566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD,0,NULL,PETSC_COPY_VALUES,&from)); 97c4762a1bSJed Brown } 989566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(global,from,local,to,&scatter2)); 999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&to)); 1009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 101c4762a1bSJed Brown 102c4762a1bSJed Brown /* 103c4762a1bSJed Brown fill the global vector with the natural global numbering for each local entry 104c4762a1bSJed Brown this is only done for testing purposes since it is easy to see if the scatter worked correctly 105c4762a1bSJed Brown */ 1069566063dSJacob Faibussowitsch PetscCall(DMDACreateNaturalVector(da,&natural)); 1079566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(natural,&start,&end)); 1089566063dSJacob Faibussowitsch PetscCall(VecGetArray(natural,&xnatural)); 109c4762a1bSJed Brown for (i=start; i<end; i++) { 110c4762a1bSJed Brown xnatural[i-start] = i; 111c4762a1bSJed Brown } 1129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(natural,&xnatural)); 1139566063dSJacob Faibussowitsch PetscCall(DMDANaturalToGlobalBegin(da,natural,INSERT_VALUES,global)); 1149566063dSJacob Faibussowitsch PetscCall(DMDANaturalToGlobalEnd(da,natural,INSERT_VALUES,global)); 1159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&natural)); 116c4762a1bSJed Brown 117c4762a1bSJed Brown /* scatter from global to local */ 1189566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scatter1,global,local,INSERT_VALUES,SCATTER_FORWARD)); 1199566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scatter1,global,local,INSERT_VALUES,SCATTER_FORWARD)); 1209566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scatter2,global,local,INSERT_VALUES,SCATTER_FORWARD)); 1219566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scatter2,global,local,INSERT_VALUES,SCATTER_FORWARD)); 122c4762a1bSJed Brown /* 123c4762a1bSJed Brown normally here you would also call 1249566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da,global,INSERT_VALUES,local)); 1259566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da,global,INSERT_VALUES,local)); 126c4762a1bSJed Brown to update all the interior ghost cells between neighboring processes. 127c4762a1bSJed Brown We don't do it here since this is only a test of "special" ghost points. 128c4762a1bSJed Brown */ 129c4762a1bSJed Brown 130c4762a1bSJed Brown /* view each local ghosted vector */ 1319566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(PETSC_VIEWER_STDOUT_WORLD,PETSC_COMM_SELF,&subviewer)); 1329566063dSJacob Faibussowitsch PetscCall(VecView(local,subviewer)); 1339566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(PETSC_VIEWER_STDOUT_WORLD,PETSC_COMM_SELF,&subviewer)); 134c4762a1bSJed Brown 1359566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&scatter1)); 1369566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&scatter2)); 1379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&local)); 1389566063dSJacob Faibussowitsch PetscCall(VecDestroy(&global)); 1399566063dSJacob Faibussowitsch PetscCall(DMDestroy(&da)); 1409566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 141b122ec5aSJacob Faibussowitsch return 0; 142c4762a1bSJed Brown } 143c4762a1bSJed Brown 144c4762a1bSJed Brown /*TEST 145c4762a1bSJed Brown 146c4762a1bSJed Brown test: 147c4762a1bSJed Brown 148c4762a1bSJed Brown test: 149c4762a1bSJed Brown suffix: 2 150c4762a1bSJed Brown nsize: 2 151c4762a1bSJed Brown 152c4762a1bSJed Brown test: 153c4762a1bSJed Brown suffix: 4 154c4762a1bSJed Brown nsize: 4 155c4762a1bSJed Brown 156c4762a1bSJed Brown test: 157c4762a1bSJed Brown suffix: 9 158c4762a1bSJed Brown nsize: 9 159c4762a1bSJed Brown 160c4762a1bSJed Brown TEST*/ 161