xref: /petsc/src/dm/tutorials/swarm_ex3.c (revision 6a5217c03994f2d95bb2e6dbd8bed42381aeb015)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "Tests DMSwarm with DMShell\n\n";
3c4762a1bSJed Brown 
4c4762a1bSJed Brown #include <petscsf.h>
5c4762a1bSJed Brown #include <petscdm.h>
6c4762a1bSJed Brown #include <petscdmshell.h>
7c4762a1bSJed Brown #include <petscdmda.h>
8c4762a1bSJed Brown #include <petscdmswarm.h>
9c4762a1bSJed Brown #include <petsc/private/dmimpl.h>
10c4762a1bSJed Brown 
11c4762a1bSJed Brown PetscErrorCode _DMLocatePoints_DMDARegular_IS(DM dm,Vec pos,IS *iscell)
12c4762a1bSJed Brown {
13c4762a1bSJed Brown   PetscInt       p,n,bs,npoints,si,sj,milocal,mjlocal,mx,my;
14c4762a1bSJed Brown   DM             dmregular;
15c4762a1bSJed Brown   PetscInt       *cellidx;
16c4762a1bSJed Brown   const PetscScalar *coor;
17c4762a1bSJed Brown   PetscReal      dx,dy;
18c4762a1bSJed Brown   PetscMPIInt    rank;
19c4762a1bSJed Brown 
20362febeeSStefano Zampini   PetscFunctionBegin;
219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
229566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(pos,&n));
239566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(pos,&bs));
24c4762a1bSJed Brown   npoints = n/bs;
25c4762a1bSJed Brown 
269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(npoints,&cellidx));
279566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dm,&dmregular));
289566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(dmregular,&si,&sj,NULL,&milocal,&mjlocal,NULL));
299566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(dmregular,NULL,&mx,&my,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL));
30c4762a1bSJed Brown 
31c4762a1bSJed Brown   dx = 2.0/((PetscReal)mx);
32c4762a1bSJed Brown   dy = 2.0/((PetscReal)my);
33c4762a1bSJed Brown 
349566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(pos,&coor));
35c4762a1bSJed Brown   for (p=0; p<npoints; p++) {
36c4762a1bSJed Brown     PetscReal coorx,coory;
37c4762a1bSJed Brown     PetscInt  mi,mj;
38c4762a1bSJed Brown 
39c4762a1bSJed Brown     coorx = PetscRealPart(coor[2*p]);
40c4762a1bSJed Brown     coory = PetscRealPart(coor[2*p+1]);
41c4762a1bSJed Brown 
42c4762a1bSJed Brown     mi = (PetscInt)( (coorx - (-1.0))/dx);
43c4762a1bSJed Brown     mj = (PetscInt)( (coory - (-1.0))/dy);
44c4762a1bSJed Brown 
45c4762a1bSJed Brown     cellidx[p] = DMLOCATEPOINT_POINT_NOT_FOUND;
46c4762a1bSJed Brown 
47c4762a1bSJed Brown     if ((mj >= sj) && (mj < sj + mjlocal)) {
48c4762a1bSJed Brown       if ((mi >= si) && (mi < si + milocal)) {
49c4762a1bSJed Brown         cellidx[p] = (mi-si) + (mj-sj) * milocal;
50c4762a1bSJed Brown       }
51c4762a1bSJed Brown     }
52c4762a1bSJed Brown     if (coorx < -1.0) cellidx[p] = DMLOCATEPOINT_POINT_NOT_FOUND;
53c4762a1bSJed Brown     if (coorx >  1.0) cellidx[p] = DMLOCATEPOINT_POINT_NOT_FOUND;
54c4762a1bSJed Brown     if (coory < -1.0) cellidx[p] = DMLOCATEPOINT_POINT_NOT_FOUND;
55c4762a1bSJed Brown     if (coory >  1.0) cellidx[p] = DMLOCATEPOINT_POINT_NOT_FOUND;
56c4762a1bSJed Brown   }
579566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(pos,&coor));
589566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PETSC_COMM_SELF,npoints,cellidx,PETSC_OWN_POINTER,iscell));
59c4762a1bSJed Brown   PetscFunctionReturn(0);
60c4762a1bSJed Brown }
61c4762a1bSJed Brown 
62c4762a1bSJed Brown PetscErrorCode DMLocatePoints_DMDARegular(DM dm,Vec pos,DMPointLocationType ltype, PetscSF cellSF)
63c4762a1bSJed Brown {
64c4762a1bSJed Brown   IS             iscell;
65c4762a1bSJed Brown   PetscSFNode    *cells;
66c4762a1bSJed Brown   PetscInt       p,bs,npoints,nfound;
67c4762a1bSJed Brown   const PetscInt *boxCells;
68c4762a1bSJed Brown 
69362febeeSStefano Zampini   PetscFunctionBegin;
709566063dSJacob Faibussowitsch   PetscCall(_DMLocatePoints_DMDARegular_IS(dm,pos,&iscell));
719566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(pos,&npoints));
729566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(pos,&bs));
73c4762a1bSJed Brown   npoints = npoints / bs;
74c4762a1bSJed Brown 
759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(npoints, &cells));
769566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(iscell, &boxCells));
77c4762a1bSJed Brown 
78c4762a1bSJed Brown   for (p=0; p<npoints; p++) {
79c4762a1bSJed Brown     cells[p].rank  = 0;
80c4762a1bSJed Brown     cells[p].index = DMLOCATEPOINT_POINT_NOT_FOUND;
81c4762a1bSJed Brown     cells[p].index = boxCells[p];
82c4762a1bSJed Brown   }
839566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(iscell, &boxCells));
849566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&iscell));
85c4762a1bSJed Brown   nfound = npoints;
869566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(cellSF, npoints, nfound, NULL, PETSC_OWN_POINTER, cells, PETSC_OWN_POINTER));
879566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&iscell));
88c4762a1bSJed Brown   PetscFunctionReturn(0);
89c4762a1bSJed Brown }
90c4762a1bSJed Brown 
91c4762a1bSJed Brown PetscErrorCode DMGetNeighbors_DMDARegular(DM dm,PetscInt *nneighbors,const PetscMPIInt **neighbors)
92c4762a1bSJed Brown {
93c4762a1bSJed Brown   DM             dmregular;
94c4762a1bSJed Brown 
95362febeeSStefano Zampini   PetscFunctionBegin;
969566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dm,&dmregular));
979566063dSJacob Faibussowitsch   PetscCall(DMGetNeighbors(dmregular,nneighbors,neighbors));
98c4762a1bSJed Brown   PetscFunctionReturn(0);
99c4762a1bSJed Brown }
100c4762a1bSJed Brown 
101c4762a1bSJed Brown PetscErrorCode SwarmViewGP(DM dms,const char prefix[])
102c4762a1bSJed Brown {
103c4762a1bSJed Brown   PetscReal      *array;
104c4762a1bSJed Brown   PetscInt       *iarray;
105c4762a1bSJed Brown   PetscInt       npoints,p,bs;
106c4762a1bSJed Brown   FILE           *fp;
107c4762a1bSJed Brown   char           name[PETSC_MAX_PATH_LEN];
108c4762a1bSJed Brown   PetscMPIInt    rank;
109c4762a1bSJed Brown 
110362febeeSStefano Zampini   PetscFunctionBegin;
1119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
1129566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"%s-rank%d.gp",prefix,rank));
113c4762a1bSJed Brown   fp = fopen(name,"w");
11428b400f6SJacob Faibussowitsch   PetscCheck(fp,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s",name);
1159566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dms,&npoints));
1169566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dms,DMSwarmPICField_coor,&bs,NULL,(void**)&array));
1179566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dms,"itag",NULL,NULL,(void**)&iarray));
118c4762a1bSJed Brown   for (p=0; p<npoints; p++) {
119c4762a1bSJed Brown     fprintf(fp,"%+1.4e %+1.4e %1.4e\n",array[2*p],array[2*p+1],(double)iarray[p]);
120c4762a1bSJed Brown   }
1219566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dms,"itag",NULL,NULL,(void**)&iarray));
1229566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dms,DMSwarmPICField_coor,&bs,NULL,(void**)&array));
123c4762a1bSJed Brown   fclose(fp);
124c4762a1bSJed Brown   PetscFunctionReturn(0);
125c4762a1bSJed Brown }
126c4762a1bSJed Brown 
127c4762a1bSJed Brown /*
128c4762a1bSJed Brown  Create a DMShell and attach a regularly spaced DMDA for point location
129c4762a1bSJed Brown  Override methods for point location
130c4762a1bSJed Brown */
131c4762a1bSJed Brown PetscErrorCode ex3_1(void)
132c4762a1bSJed Brown {
133c4762a1bSJed Brown   DM             dms,dmcell,dmregular;
134c4762a1bSJed Brown   PetscMPIInt    rank;
135c4762a1bSJed Brown   PetscInt       p,bs,nlocal,overlap,mx,tk;
136c4762a1bSJed Brown   PetscReal      dx;
137c4762a1bSJed Brown   PetscReal      *array,dt;
138c4762a1bSJed Brown   PetscInt       *iarray;
139c4762a1bSJed Brown   PetscRandom    rand;
140c4762a1bSJed Brown 
141362febeeSStefano Zampini   PetscFunctionBegin;
1429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
143c4762a1bSJed Brown 
144c4762a1bSJed Brown   /* Create a regularly spaced DMDA */
145c4762a1bSJed Brown   mx = 40;
146c4762a1bSJed Brown   overlap = 0;
1479566063dSJacob Faibussowitsch   PetscCall(DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,mx,mx,PETSC_DECIDE,PETSC_DECIDE,1,overlap,NULL,NULL,&dmregular));
1489566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(dmregular));
1499566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dmregular));
150c4762a1bSJed Brown 
151c4762a1bSJed Brown   dx = 2.0/((PetscReal)mx);
1529566063dSJacob Faibussowitsch   PetscCall(DMDASetUniformCoordinates(dmregular,-1.0+0.5*dx,1.0-0.5*dx,-1.0+0.5*dx,1.0-0.5*dx,-1.0,1.0));
153c4762a1bSJed Brown 
154c4762a1bSJed Brown   /* Create a DMShell for point location purposes */
1559566063dSJacob Faibussowitsch   PetscCall(DMShellCreate(PETSC_COMM_WORLD,&dmcell));
1569566063dSJacob Faibussowitsch   PetscCall(DMSetApplicationContext(dmcell,dmregular));
157c4762a1bSJed Brown   dmcell->ops->locatepoints = DMLocatePoints_DMDARegular;
158c4762a1bSJed Brown   dmcell->ops->getneighbors = DMGetNeighbors_DMDARegular;
159c4762a1bSJed Brown 
160c4762a1bSJed Brown   /* Create the swarm */
1619566063dSJacob Faibussowitsch   PetscCall(DMCreate(PETSC_COMM_WORLD,&dms));
1629566063dSJacob Faibussowitsch   PetscCall(DMSetType(dms,DMSWARM));
1639566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dms,2));
164*6a5217c0SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject) dms, "Particles"));
165c4762a1bSJed Brown 
1669566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetType(dms,DMSWARM_PIC));
1679566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetCellDM(dms,dmcell));
168c4762a1bSJed Brown 
1699566063dSJacob Faibussowitsch   PetscCall(DMSwarmRegisterPetscDatatypeField(dms,"itag",1,PETSC_INT));
1709566063dSJacob Faibussowitsch   PetscCall(DMSwarmFinalizeFieldRegister(dms));
171c4762a1bSJed Brown   {
172c4762a1bSJed Brown     PetscInt  si,sj,milocal,mjlocal;
173c4762a1bSJed Brown     const PetscScalar *LA_coors;
174c4762a1bSJed Brown     Vec       coors;
175c4762a1bSJed Brown     PetscInt  cnt;
176c4762a1bSJed Brown 
1779566063dSJacob Faibussowitsch     PetscCall(DMDAGetCorners(dmregular,&si,&sj,NULL,&milocal,&mjlocal,NULL));
1789566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinates(dmregular,&coors));
1799566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(coors,&LA_coors));
1809566063dSJacob Faibussowitsch     PetscCall(DMSwarmSetLocalSizes(dms,milocal*mjlocal,4));
1819566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetLocalSize(dms,&nlocal));
1829566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dms,DMSwarmPICField_coor,&bs,NULL,(void**)&array));
183c4762a1bSJed Brown     cnt = 0;
1849566063dSJacob Faibussowitsch     PetscCall(PetscRandomCreate(PETSC_COMM_SELF,&rand));
1859566063dSJacob Faibussowitsch     PetscCall(PetscRandomSetInterval(rand,-1.0,1.0));
186c4762a1bSJed Brown     for (p=0; p<nlocal; p++) {
187c4762a1bSJed Brown       PetscReal px,py,rx,ry,r2;
188c4762a1bSJed Brown 
1899566063dSJacob Faibussowitsch       PetscCall(PetscRandomGetValueReal(rand,&rx));
1909566063dSJacob Faibussowitsch       PetscCall(PetscRandomGetValueReal(rand,&ry));
191c4762a1bSJed Brown 
192c4762a1bSJed Brown       px = PetscRealPart(LA_coors[2*p+0]) + 0.1*rx*dx;
193c4762a1bSJed Brown       py = PetscRealPart(LA_coors[2*p+1]) + 0.1*ry*dx;
194c4762a1bSJed Brown 
195c4762a1bSJed Brown       r2 = px*px + py*py;
196c4762a1bSJed Brown       if (r2 < 0.75*0.75) {
197c4762a1bSJed Brown         array[bs*cnt+0] = px;
198c4762a1bSJed Brown         array[bs*cnt+1] = py;
199c4762a1bSJed Brown         cnt++;
200c4762a1bSJed Brown       }
201c4762a1bSJed Brown     }
2029566063dSJacob Faibussowitsch     PetscCall(PetscRandomDestroy(&rand));
2039566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dms,DMSwarmPICField_coor,&bs,NULL,(void**)&array));
2049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(coors,&LA_coors));
2059566063dSJacob Faibussowitsch     PetscCall(DMSwarmSetLocalSizes(dms,cnt,4));
206c4762a1bSJed Brown 
2079566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetLocalSize(dms,&nlocal));
2089566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dms,"itag",&bs,NULL,(void**)&iarray));
209c4762a1bSJed Brown     for (p=0; p<nlocal; p++) {
210c4762a1bSJed Brown       iarray[p] = (PetscInt)rank;
211c4762a1bSJed Brown     }
2129566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dms,"itag",&bs,NULL,(void**)&iarray));
213c4762a1bSJed Brown   }
214c4762a1bSJed Brown 
2159566063dSJacob Faibussowitsch   PetscCall(DMView(dms,PETSC_VIEWER_STDOUT_WORLD));
2169566063dSJacob Faibussowitsch   PetscCall(SwarmViewGP(dms,"step0"));
217c4762a1bSJed Brown 
218c4762a1bSJed Brown   dt = 0.1;
219c4762a1bSJed Brown   for (tk=1; tk<20; tk++) {
220c4762a1bSJed Brown     char prefix[PETSC_MAX_PATH_LEN];
2219566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Step %D \n",tk));
222c4762a1bSJed Brown     /* push points */
2239566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetLocalSize(dms,&nlocal));
2249566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dms,DMSwarmPICField_coor,&bs,NULL,(void**)&array));
225c4762a1bSJed Brown     for (p=0; p<nlocal; p++) {
226c4762a1bSJed Brown       PetscReal cx,cy,vx,vy;
227c4762a1bSJed Brown 
228c4762a1bSJed Brown       cx = array[2*p];
229c4762a1bSJed Brown       cy = array[2*p+1];
230c4762a1bSJed Brown       vx =  cy;
231c4762a1bSJed Brown       vy = -cx;
232c4762a1bSJed Brown 
233c4762a1bSJed Brown       array[2*p  ] += dt * vx;
234c4762a1bSJed Brown       array[2*p+1] += dt * vy;
235c4762a1bSJed Brown     }
2369566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dms,DMSwarmPICField_coor,&bs,NULL,(void**)&array));
237c4762a1bSJed Brown 
238c4762a1bSJed Brown     /* migrate points */
2399566063dSJacob Faibussowitsch     PetscCall(DMSwarmMigrate(dms,PETSC_TRUE));
240c4762a1bSJed Brown     /* view points */
2419566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(prefix,PETSC_MAX_PATH_LEN-1,"step%d",tk));
242c4762a1bSJed Brown     /* should use the regular SwarmView() api, not one for a particular type */
2439566063dSJacob Faibussowitsch     PetscCall(SwarmViewGP(dms,prefix));
244c4762a1bSJed Brown   }
2459566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmregular));
2469566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmcell));
2479566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dms));
248c4762a1bSJed Brown   PetscFunctionReturn(0);
249c4762a1bSJed Brown }
250c4762a1bSJed Brown 
251c4762a1bSJed Brown int main(int argc,char **argv)
252c4762a1bSJed Brown {
253c4762a1bSJed Brown 
2549566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc,&argv,(char*)0,help));
2559566063dSJacob Faibussowitsch   PetscCall(ex3_1());
2569566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
257b122ec5aSJacob Faibussowitsch   return 0;
258c4762a1bSJed Brown }
259c4762a1bSJed Brown 
260c4762a1bSJed Brown /*TEST
261c4762a1bSJed Brown 
262c4762a1bSJed Brown    build:
263c4762a1bSJed Brown       requires: double !complex
264c4762a1bSJed Brown 
265c4762a1bSJed Brown    test:
266c4762a1bSJed Brown       filter: grep -v atomic
267c4762a1bSJed Brown       filter_output: grep -v atomic
268c4762a1bSJed Brown TEST*/
269