xref: /petsc/src/dm/impls/swarm/swarm_migrate.c (revision 9566063d113dddea24716c546802770db7481bc0)
1dfc14de9SMatthew G. Knepley #include <petscsf.h>
208056efcSDave May #include <petscdmswarm.h>
35917a6f0SStefano Zampini #include <petscdmda.h>
4df21e3a8SDave May #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
5279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
6279f676cSBarry Smith #include "../src/dm/impls/swarm/data_ex.h"
7df21e3a8SDave May 
8480eef7bSDave May /*
9480eef7bSDave May  User loads desired location (MPI rank) into field DMSwarm_rank
10480eef7bSDave May */
11df21e3a8SDave May PetscErrorCode DMSwarmMigrate_Push_Basic(DM dm,PetscBool remove_sent_points)
12df21e3a8SDave May {
13df21e3a8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1477048351SPatrick Sanan   DMSwarmDataEx  de;
15df21e3a8SDave May   PetscInt       p,npoints,*rankval,n_points_recv;
16df21e3a8SDave May   PetscMPIInt    rank,nrank;
17df21e3a8SDave May   void           *point_buffer,*recv_points;
18df21e3a8SDave May   size_t         sizeof_dmswarm_point;
19df21e3a8SDave May 
20521f74f9SMatthew G. Knepley   PetscFunctionBegin;
21*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank));
22df21e3a8SDave May 
23*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
24*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
25*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm),0, &de));
26*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
27521f74f9SMatthew G. Knepley   for (p = 0; p < npoints; ++p) {
28df21e3a8SDave May     nrank = rankval[p];
29df21e3a8SDave May     if (nrank != rank) {
30*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExTopologyAddNeighbour(de,nrank));
31df21e3a8SDave May     }
32df21e3a8SDave May   }
33*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
34*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
35df21e3a8SDave May   for (p=0; p<npoints; p++) {
36df21e3a8SDave May     nrank = rankval[p];
37df21e3a8SDave May     if (nrank != rank) {
38*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExAddToSendCount(de,nrank,1));
39df21e3a8SDave May     }
40df21e3a8SDave May   }
41*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
42*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db,&sizeof_dmswarm_point,&point_buffer));
43*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de,sizeof_dmswarm_point));
44df21e3a8SDave May   for (p=0; p<npoints; p++) {
45df21e3a8SDave May     nrank = rankval[p];
46df21e3a8SDave May     if (nrank != rank) {
47df21e3a8SDave May       /* copy point into buffer */
48*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db,p,point_buffer));
4977048351SPatrick Sanan       /* insert point buffer into DMSwarmDataExchanger */
50*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de,nrank,1,point_buffer));
51df21e3a8SDave May     }
52df21e3a8SDave May   }
53*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
54*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
55df21e3a8SDave May 
56df21e3a8SDave May   if (remove_sent_points) {
5777048351SPatrick Sanan     DMSwarmDataField gfield;
5822a417f9SDave May 
59*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,DMSwarmField_rank,&gfield));
60*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetAccess(gfield));
61*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetEntries(gfield,(void**)&rankval));
6222a417f9SDave May 
63df21e3a8SDave May     /* remove points which left processor */
64*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
65df21e3a8SDave May     for (p=0; p<npoints; p++) {
66df21e3a8SDave May       nrank = rankval[p];
67df21e3a8SDave May       if (nrank != rank) {
68df21e3a8SDave May         /* kill point */
69*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
7022a417f9SDave May 
71*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db,p));
7222a417f9SDave May 
73*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL)); /* you need to update npoints as the list size decreases! */
74*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetAccess(gfield));
75*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetEntries(gfield,(void**)&rankval));
76df21e3a8SDave May         p--; /* check replacement point */
77df21e3a8SDave May       }
78df21e3a8SDave May     }
79*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldRestoreEntries(gfield,(void**)&rankval));
80*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
81df21e3a8SDave May   }
82*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
83*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
84*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExGetRecvData(de,&n_points_recv,(void**)&recv_points));
85*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
86*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db,npoints + n_points_recv,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
87df21e3a8SDave May   for (p=0; p<n_points_recv; p++) {
88df21e3a8SDave May     void *data_p = (void*)( (char*)recv_points + p*sizeof_dmswarm_point);
89df21e3a8SDave May 
90*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db,npoints+p,data_p));
91df21e3a8SDave May   }
92*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExView(de));
93*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db,&point_buffer));
94*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
95df21e3a8SDave May   PetscFunctionReturn(0);
96df21e3a8SDave May }
972712d1f2SDave May 
98889dbfe5SDave May PetscErrorCode DMSwarmMigrate_DMNeighborScatter(DM dm,DM dmcell,PetscBool remove_sent_points,PetscInt *npoints_prior_migration)
9940c453e9SDave May {
10040c453e9SDave May   DM_Swarm          *swarm = (DM_Swarm*)dm->data;
10177048351SPatrick Sanan   DMSwarmDataEx     de;
10240c453e9SDave May   PetscInt          r,p,npoints,*rankval,n_points_recv;
10340c453e9SDave May   PetscMPIInt       rank,_rank;
10440c453e9SDave May   const PetscMPIInt *neighbourranks;
10540c453e9SDave May   void              *point_buffer,*recv_points;
10640c453e9SDave May   size_t            sizeof_dmswarm_point;
10740c453e9SDave May   PetscInt          nneighbors;
1087c6d1d28SDave May   PetscMPIInt       mynneigh,*myneigh;
10940c453e9SDave May 
110521f74f9SMatthew G. Knepley   PetscFunctionBegin;
111*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank));
112*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
113*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
114*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm),0,&de));
115*9566063dSJacob Faibussowitsch   PetscCall(DMGetNeighbors(dmcell,&nneighbors,&neighbourranks));
116*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
11740c453e9SDave May   for (r=0; r<nneighbors; r++) {
11840c453e9SDave May     _rank = neighbourranks[r];
11940c453e9SDave May     if ((_rank != rank) && (_rank > 0)) {
120*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExTopologyAddNeighbour(de,_rank));
12140c453e9SDave May     }
12240c453e9SDave May   }
123*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
124*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyGetNeighbours(de,&mynneigh,&myneigh));
125*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
12640c453e9SDave May   for (p=0; p<npoints; p++) {
127f954cb40SDave May     if (rankval[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
1287c6d1d28SDave May       for (r=0; r<mynneigh; r++) {
1297c6d1d28SDave May         _rank = myneigh[r];
130*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataExAddToSendCount(de,_rank,1));
13140c453e9SDave May       }
13240c453e9SDave May     }
13340c453e9SDave May   }
134*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
135*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db,&sizeof_dmswarm_point,&point_buffer));
136*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de,sizeof_dmswarm_point));
13740c453e9SDave May   for (p=0; p<npoints; p++) {
138f954cb40SDave May     if (rankval[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
1397c6d1d28SDave May       for (r=0; r<mynneigh; r++) {
1407c6d1d28SDave May         _rank = myneigh[r];
14140c453e9SDave May         /* copy point into buffer */
142*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db,p,point_buffer));
14377048351SPatrick Sanan         /* insert point buffer into DMSwarmDataExchanger */
144*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataExPackData(de,_rank,1,point_buffer));
14540c453e9SDave May       }
14640c453e9SDave May     }
14740c453e9SDave May   }
148*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
149*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
15040c453e9SDave May   if (remove_sent_points) {
15177048351SPatrick Sanan     DMSwarmDataField PField;
1527c6d1d28SDave May 
153*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,DMSwarmField_rank,&PField));
154*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval));
15540c453e9SDave May     /* remove points which left processor */
156*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
15740c453e9SDave May     for (p=0; p<npoints; p++) {
158f954cb40SDave May       if (rankval[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
15940c453e9SDave May         /* kill point */
160*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db,p));
161*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL)); /* you need to update npoints as the list size decreases! */
162*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval)); /* update date point increase realloc performed */
16340c453e9SDave May         p--; /* check replacement point */
16440c453e9SDave May       }
16540c453e9SDave May     }
16640c453e9SDave May   }
167*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,npoints_prior_migration,NULL,NULL));
168*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
169*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
170*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExGetRecvData(de,&n_points_recv,(void**)&recv_points));
171*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
172*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db,npoints + n_points_recv,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
17340c453e9SDave May   for (p=0; p<n_points_recv; p++) {
17440c453e9SDave May     void *data_p = (void*)( (char*)recv_points + p*sizeof_dmswarm_point);
17540c453e9SDave May 
176*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db,npoints+p,data_p));
17740c453e9SDave May   }
178*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db,&point_buffer));
179*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
18040c453e9SDave May   PetscFunctionReturn(0);
18140c453e9SDave May }
182480eef7bSDave May 
18308056efcSDave May PetscErrorCode DMSwarmMigrate_CellDMScatter(DM dm,PetscBool remove_sent_points)
184480eef7bSDave May {
185480eef7bSDave May   DM_Swarm          *swarm = (DM_Swarm*)dm->data;
1866fbf25f8SDave May   PetscInt          p,npoints,npointsg=0,npoints2,npoints2g,*rankval,npoints_prior_migration;
187bbe8250bSMatthew G. Knepley   PetscSF           sfcell = NULL;
188dfc14de9SMatthew G. Knepley   const PetscSFNode *LA_sfcell;
189480eef7bSDave May   DM                dmcell;
190480eef7bSDave May   Vec               pos;
19140c453e9SDave May   PetscBool         error_check = swarm->migrate_error_on_missing_point;
192e4fbd051SBarry Smith   PetscMPIInt       size,rank;
193480eef7bSDave May 
194521f74f9SMatthew G. Knepley   PetscFunctionBegin;
195*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm,&dmcell));
19628b400f6SJacob Faibussowitsch   PetscCheck(dmcell,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid if cell DM provided");
197480eef7bSDave May 
198*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size));
199*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank));
2007c6d1d28SDave May 
20143a82f2bSDave May #if 1
20243a82f2bSDave May   {
20343a82f2bSDave May     PetscInt *p_cellid;
20443a82f2bSDave May     PetscInt npoints_curr,range = 0;
20543a82f2bSDave May     PetscSFNode *sf_cells;
20643a82f2bSDave May 
207*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints_curr,NULL,NULL));
208*9566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(npoints_curr, &sf_cells));
20943a82f2bSDave May 
210*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
211*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&p_cellid));
21243a82f2bSDave May     for (p=0; p<npoints_curr; p++) {
21343a82f2bSDave May 
21443a82f2bSDave May       sf_cells[p].rank  = 0;
21543a82f2bSDave May       sf_cells[p].index = p_cellid[p];
21643a82f2bSDave May       if (p_cellid[p] > range) {
21743a82f2bSDave May         range = p_cellid[p];
21843a82f2bSDave May       }
21943a82f2bSDave May     }
220*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&p_cellid));
221*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
22243a82f2bSDave May 
223*9566063dSJacob Faibussowitsch     /* PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&sfcell)); */
224*9566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sfcell));
225*9566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfcell, range, npoints_curr, NULL, PETSC_OWN_POINTER, sf_cells, PETSC_OWN_POINTER));
22643a82f2bSDave May   }
22743a82f2bSDave May #endif
22843a82f2bSDave May 
229*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateLocalVectorFromField(dm, DMSwarmPICField_coor, &pos));
230*9566063dSJacob Faibussowitsch   PetscCall(DMLocatePoints(dmcell, pos, DM_POINTLOCATION_NONE, &sfcell));
231*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyLocalVectorFromField(dm, DMSwarmPICField_coor, &pos));
232480eef7bSDave May 
23340c453e9SDave May   if (error_check) {
234*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetSize(dm,&npointsg));
23540c453e9SDave May   }
236*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
237*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
238*9566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell));
239480eef7bSDave May   for (p=0; p<npoints; p++) {
240dfc14de9SMatthew G. Knepley     rankval[p] = LA_sfcell[p].index;
241480eef7bSDave May   }
242*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
243*9566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfcell));
244480eef7bSDave May 
245e4fbd051SBarry Smith   if (size > 1) {
246*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmMigrate_DMNeighborScatter(dm,dmcell,remove_sent_points,&npoints_prior_migration));
2476fbf25f8SDave May   } else {
24877048351SPatrick Sanan     DMSwarmDataField PField;
2490ed23c7fSDave May     PetscInt npoints_curr;
2500ed23c7fSDave May 
2510ed23c7fSDave May     /* remove points which the domain */
252*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,DMSwarmField_rank,&PField));
253*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval));
2540ed23c7fSDave May 
255*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints_curr,NULL,NULL));
2560ed23c7fSDave May     for (p=0; p<npoints_curr; p++) {
2570ed23c7fSDave May       if (rankval[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
2580ed23c7fSDave May         /* kill point */
259*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db,p));
260*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints_curr,NULL,NULL)); /* you need to update npoints as the list size decreases! */
261*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval)); /* update date point increase realloc performed */
2620ed23c7fSDave May         p--; /* check replacement point */
2630ed23c7fSDave May       }
2640ed23c7fSDave May     }
265*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetSize(dm,&npoints_prior_migration));
2660ed23c7fSDave May 
2676fbf25f8SDave May   }
268480eef7bSDave May 
2692d4ee042Sprj-   /* locate points newly received */
270*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL));
271009b43efSDave May 
2727c6d1d28SDave May #if 0
2732d4ee042Sprj-   { /* safe alternative - however this performs two point locations on: (i) the initial points set and; (ii) the (initial + received) point set */
2747c6d1d28SDave May     PetscScalar *LA_coor;
2757c6d1d28SDave May     PetscInt bs;
27677048351SPatrick Sanan     DMSwarmDataField PField;
2777c6d1d28SDave May 
278*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmPICField_coor,&bs,NULL,(void**)&LA_coor));
279*9566063dSJacob Faibussowitsch     PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,bs,bs*npoints2,(const PetscScalar*)LA_coor,&pos));
280*9566063dSJacob Faibussowitsch     PetscCall(DMLocatePoints(dmcell,pos,DM_POINTLOCATION_NONE,&sfcell));
2817c6d1d28SDave May 
282*9566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pos));
283*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmPICField_coor,&bs,NULL,(void**)&LA_coor));
2847c6d1d28SDave May 
285*9566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell));
286*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
2877c6d1d28SDave May     for (p=0; p<npoints2; p++) {
288dfc14de9SMatthew G. Knepley       rankval[p] = LA_sfcell[p].index;
2897c6d1d28SDave May     }
290*9566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfcell));
291*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
29240c453e9SDave May 
2937c6d1d28SDave May     /* remove points which left processor */
294*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,DMSwarmField_rank,&PField));
295*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval));
2967c6d1d28SDave May 
297*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL));
2987c6d1d28SDave May     for (p=0; p<npoints2; p++) {
299f954cb40SDave May       if (rankval[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
3007c6d1d28SDave May         /* kill point */
301*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db,p));
302*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL)); /* you need to update npoints as the list size decreases! */
303*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval)); /* update date point increase realloc performed */
3047c6d1d28SDave May         p--; /* check replacement point */
3057c6d1d28SDave May       }
3067c6d1d28SDave May     }
30740c453e9SDave May   }
308009b43efSDave May #endif
309009b43efSDave May 
3105627991aSBarry Smith   { /* perform two point locations: (i) on the initial points set prior to communication; and (ii) on the new (received) points */
311009b43efSDave May     PetscScalar      *LA_coor;
312009b43efSDave May     PetscInt         npoints_from_neighbours,bs;
31377048351SPatrick Sanan     DMSwarmDataField PField;
314009b43efSDave May 
315009b43efSDave May     npoints_from_neighbours = npoints2 - npoints_prior_migration;
316009b43efSDave May 
317*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmPICField_coor,&bs,NULL,(void**)&LA_coor));
318*9566063dSJacob Faibussowitsch     PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,bs,bs*npoints_from_neighbours,(const PetscScalar*)&LA_coor[bs*npoints_prior_migration],&pos));
319009b43efSDave May 
320*9566063dSJacob Faibussowitsch     PetscCall(DMLocatePoints(dmcell,pos,DM_POINTLOCATION_NONE,&sfcell));
321009b43efSDave May 
322*9566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pos));
323*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmPICField_coor,&bs,NULL,(void**)&LA_coor));
324009b43efSDave May 
325*9566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell));
326*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
327009b43efSDave May     for (p=0; p<npoints_from_neighbours; p++) {
328009b43efSDave May       rankval[npoints_prior_migration + p] = LA_sfcell[p].index;
329009b43efSDave May     }
330*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
331*9566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfcell));
332009b43efSDave May 
333009b43efSDave May     /* remove points which left processor */
334*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,DMSwarmField_rank,&PField));
335*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval));
336009b43efSDave May 
337*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL));
338009b43efSDave May     for (p=npoints_prior_migration; p<npoints2; p++) {
339009b43efSDave May       if (rankval[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
340009b43efSDave May         /* kill point */
341*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db,p));
342*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL)); /* you need to update npoints as the list size decreases! */
343*9566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval)); /* update date point increase realloc performed */
344009b43efSDave May         p--; /* check replacement point */
345009b43efSDave May       }
346009b43efSDave May     }
347009b43efSDave May   }
348009b43efSDave May 
3493151f1d5SDave May   {
3503151f1d5SDave May     PetscInt *p_cellid;
3513151f1d5SDave May 
352*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL));
353*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
354*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&p_cellid));
3553151f1d5SDave May     for (p=0; p<npoints2; p++) {
3563151f1d5SDave May       p_cellid[p] = rankval[p];
3573151f1d5SDave May     }
358*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&p_cellid));
359*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
3603151f1d5SDave May   }
3613151f1d5SDave May 
36240c453e9SDave May   /* check for error on removed points */
36340c453e9SDave May   if (error_check) {
364*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetSize(dm,&npoints2g));
3652c71b3e2SJacob Faibussowitsch     PetscCheckFalse(npointsg != npoints2g,PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Points from the DMSwarm must remain constant during migration (initial %D - final %D)",npointsg,npoints2g);
36640c453e9SDave May   }
367480eef7bSDave May   PetscFunctionReturn(0);
368480eef7bSDave May }
369480eef7bSDave May 
37008056efcSDave May PetscErrorCode DMSwarmMigrate_CellDMExact(DM dm,PetscBool remove_sent_points)
37108056efcSDave May {
372521f74f9SMatthew G. Knepley   PetscFunctionBegin;
37308056efcSDave May   PetscFunctionReturn(0);
37408056efcSDave May }
37508056efcSDave May 
376480eef7bSDave May /*
377480eef7bSDave May  Redundant as this assumes points can only be sent to a single rank
378480eef7bSDave May */
3792712d1f2SDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize)
3802712d1f2SDave May {
3812712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
38277048351SPatrick Sanan   DMSwarmDataEx  de;
3832712d1f2SDave May   PetscInt       p,npoints,*rankval,n_points_recv;
3842712d1f2SDave May   PetscMPIInt    rank,nrank,negrank;
3852712d1f2SDave May   void           *point_buffer,*recv_points;
3862712d1f2SDave May   size_t         sizeof_dmswarm_point;
3872712d1f2SDave May 
388521f74f9SMatthew G. Knepley   PetscFunctionBegin;
389*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank));
390*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
3912712d1f2SDave May   *globalsize = npoints;
392*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
393*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm),0,&de));
394*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
3952712d1f2SDave May   for (p=0; p<npoints; p++) {
3962712d1f2SDave May     negrank = rankval[p];
3972712d1f2SDave May     if (negrank < 0) {
3982712d1f2SDave May       nrank = -negrank - 1;
399*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExTopologyAddNeighbour(de,nrank));
4002712d1f2SDave May     }
4012712d1f2SDave May   }
402*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
403*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
4042712d1f2SDave May   for (p=0; p<npoints; p++) {
4052712d1f2SDave May     negrank = rankval[p];
4062712d1f2SDave May     if (negrank < 0) {
4072712d1f2SDave May       nrank = -negrank - 1;
408*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExAddToSendCount(de,nrank,1));
4092712d1f2SDave May     }
4102712d1f2SDave May   }
411*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
412*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db,&sizeof_dmswarm_point,&point_buffer));
413*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de,sizeof_dmswarm_point));
4142712d1f2SDave May   for (p=0; p<npoints; p++) {
4152712d1f2SDave May     negrank = rankval[p];
4162712d1f2SDave May     if (negrank < 0) {
4172712d1f2SDave May       nrank = -negrank - 1;
4182712d1f2SDave May       rankval[p] = nrank;
4192712d1f2SDave May       /* copy point into buffer */
420*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db,p,point_buffer));
42177048351SPatrick Sanan       /* insert point buffer into DMSwarmDataExchanger */
422*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de,nrank,1,point_buffer));
4232712d1f2SDave May       rankval[p] = negrank;
4242712d1f2SDave May     }
4252712d1f2SDave May   }
426*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
427*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
428*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
429*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
430*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExGetRecvData(de,&n_points_recv,(void**)&recv_points));
431*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
432*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db,npoints + n_points_recv,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
4332712d1f2SDave May   for (p=0; p<n_points_recv; p++) {
4342712d1f2SDave May     void *data_p = (void*)( (char*)recv_points + p*sizeof_dmswarm_point);
4352712d1f2SDave May 
436*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db,npoints+p,data_p));
4372712d1f2SDave May   }
438*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExView(de));
439*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db,&point_buffer));
440*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
4412712d1f2SDave May   PetscFunctionReturn(0);
4422712d1f2SDave May }
443b16650c8SDave May 
444b16650c8SDave May typedef struct {
445b16650c8SDave May   PetscMPIInt owner_rank;
446b16650c8SDave May   PetscReal   min[3],max[3];
447b16650c8SDave May } CollectBBox;
448b16650c8SDave May 
449fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollect_DMDABoundingBox(DM dm,PetscInt *globalsize)
450b16650c8SDave May {
451b16650c8SDave May   DM_Swarm *        swarm = (DM_Swarm*)dm->data;
45277048351SPatrick Sanan   DMSwarmDataEx     de;
453b16650c8SDave May   PetscInt          p,pk,npoints,*rankval,n_points_recv,n_bbox_recv,dim,neighbour_cells;
454b16650c8SDave May   PetscMPIInt       rank,nrank;
455b16650c8SDave May   void              *point_buffer,*recv_points;
456b16650c8SDave May   size_t            sizeof_dmswarm_point,sizeof_bbox_ctx;
457b16650c8SDave May   PetscBool         isdmda;
458b16650c8SDave May   CollectBBox       *bbox,*recv_bbox;
459b16650c8SDave May   const PetscMPIInt *dmneighborranks;
460b16650c8SDave May   DM                dmcell;
461b16650c8SDave May 
462521f74f9SMatthew G. Knepley   PetscFunctionBegin;
463*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank));
464b16650c8SDave May 
465*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm,&dmcell));
46628b400f6SJacob Faibussowitsch   PetscCheck(dmcell,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid if cell DM provided");
467b16650c8SDave May   isdmda = PETSC_FALSE;
468b16650c8SDave May   PetscObjectTypeCompare((PetscObject)dmcell,DMDA,&isdmda);
46928b400f6SJacob Faibussowitsch   PetscCheck(isdmda,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only DMDA support for CollectBoundingBox");
470b16650c8SDave May 
471*9566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm,&dim));
472b16650c8SDave May   sizeof_bbox_ctx = sizeof(CollectBBox);
473b16650c8SDave May   PetscMalloc1(1,&bbox);
474b16650c8SDave May   bbox->owner_rank = rank;
475b16650c8SDave May 
476b16650c8SDave May   /* compute the bounding box based on the overlapping / stenctil size */
477b16650c8SDave May   {
478b16650c8SDave May     Vec lcoor;
479b16650c8SDave May 
480*9566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dmcell,&lcoor));
481fe39f135SDave May     if (dim >= 1) {
482*9566063dSJacob Faibussowitsch       PetscCall(VecStrideMin(lcoor,0,NULL,&bbox->min[0]));
483*9566063dSJacob Faibussowitsch       PetscCall(VecStrideMax(lcoor,0,NULL,&bbox->max[0]));
484fe39f135SDave May     }
485fe39f135SDave May     if (dim >= 2) {
486*9566063dSJacob Faibussowitsch       PetscCall(VecStrideMin(lcoor,1,NULL,&bbox->min[1]));
487*9566063dSJacob Faibussowitsch       PetscCall(VecStrideMax(lcoor,1,NULL,&bbox->max[1]));
488b16650c8SDave May     }
489fe39f135SDave May     if (dim == 3) {
490*9566063dSJacob Faibussowitsch       PetscCall(VecStrideMin(lcoor,2,NULL,&bbox->min[2]));
491*9566063dSJacob Faibussowitsch       PetscCall(VecStrideMax(lcoor,2,NULL,&bbox->max[2]));
492fe39f135SDave May     }
493fe39f135SDave May   }
494*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
495b16650c8SDave May   *globalsize = npoints;
496*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
497*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm),0,&de));
498b16650c8SDave May   /* use DMDA neighbours */
499*9566063dSJacob Faibussowitsch   PetscCall(DMDAGetNeighbors(dmcell,&dmneighborranks));
5008dbd68bcSDave May   if (dim == 1) {
5018dbd68bcSDave May     neighbour_cells = 3;
5028dbd68bcSDave May   } else if (dim == 2) {
5038dbd68bcSDave May     neighbour_cells = 9;
5048dbd68bcSDave May   } else {
5058dbd68bcSDave May     neighbour_cells = 27;
5068dbd68bcSDave May   }
507*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
508b16650c8SDave May   for (p=0; p<neighbour_cells; p++) {
509b16650c8SDave May     if ((dmneighborranks[p] >= 0) && (dmneighborranks[p] != rank)) {
510*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExTopologyAddNeighbour(de,dmneighborranks[p]));
511b16650c8SDave May     }
512b16650c8SDave May   }
513*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
514*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
515b16650c8SDave May   for (p=0; p<neighbour_cells; p++) {
516b16650c8SDave May     if ((dmneighborranks[p] >= 0) && (dmneighborranks[p] != rank)) {
517*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExAddToSendCount(de,dmneighborranks[p],1));
518b16650c8SDave May     }
519b16650c8SDave May   }
520*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
521b16650c8SDave May   /* send bounding boxes */
522*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de,sizeof_bbox_ctx));
523b16650c8SDave May   for (p=0; p<neighbour_cells; p++) {
524b16650c8SDave May     nrank = dmneighborranks[p];
525b16650c8SDave May     if ((nrank >= 0) && (nrank != rank)) {
52677048351SPatrick Sanan       /* insert bbox buffer into DMSwarmDataExchanger */
527*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de,nrank,1,bbox));
528b16650c8SDave May     }
529b16650c8SDave May   }
530*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
531b16650c8SDave May   /* recv bounding boxes */
532*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
533*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
534*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExGetRecvData(de,&n_bbox_recv,(void**)&recv_bbox));
535298827fbSBarry Smith   /*  Wrong, should not be using PETSC_COMM_WORLD */
536b16650c8SDave May   for (p=0; p<n_bbox_recv; p++) {
537*9566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD,"[rank %d]: box from %d : range[%+1.4e,%+1.4e]x[%+1.4e,%+1.4e]\n",rank,recv_bbox[p].owner_rank,
538b122ec5aSJacob Faibussowitsch                                     (double)recv_bbox[p].min[0],(double)recv_bbox[p].max[0],(double)recv_bbox[p].min[1],(double)recv_bbox[p].max[1]));
539b16650c8SDave May   }
540*9566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout));
541b16650c8SDave May   /* of course this is stupid as this "generic" function should have a better way to know what the coordinates are called */
542*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
543b16650c8SDave May   for (pk=0; pk<n_bbox_recv; pk++) {
544b16650c8SDave May     PetscReal *array_x,*array_y;
545b16650c8SDave May 
546*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,"coorx",NULL,NULL,(void**)&array_x));
547*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,"coory",NULL,NULL,(void**)&array_y));
548b16650c8SDave May     for (p=0; p<npoints; p++) {
549b16650c8SDave May       if ((array_x[p] >= recv_bbox[pk].min[0]) && (array_x[p] <= recv_bbox[pk].max[0])) {
550b16650c8SDave May         if ((array_y[p] >= recv_bbox[pk].min[1]) && (array_y[p] <= recv_bbox[pk].max[1])) {
551*9566063dSJacob Faibussowitsch           PetscCall(DMSwarmDataExAddToSendCount(de,recv_bbox[pk].owner_rank,1));
552b16650c8SDave May         }
553b16650c8SDave May       }
554b16650c8SDave May     }
555*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,"coory",NULL,NULL,(void**)&array_y));
556*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,"coorx",NULL,NULL,(void**)&array_x));
557b16650c8SDave May   }
558*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
559*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db,&sizeof_dmswarm_point,&point_buffer));
560*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de,sizeof_dmswarm_point));
561b16650c8SDave May   for (pk=0; pk<n_bbox_recv; pk++) {
562b16650c8SDave May     PetscReal *array_x,*array_y;
563b16650c8SDave May 
564*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,"coorx",NULL,NULL,(void**)&array_x));
565*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,"coory",NULL,NULL,(void**)&array_y));
566b16650c8SDave May     for (p=0; p<npoints; p++) {
567b16650c8SDave May       if ((array_x[p] >= recv_bbox[pk].min[0]) && (array_x[p] <= recv_bbox[pk].max[0])) {
568b16650c8SDave May         if ((array_y[p] >= recv_bbox[pk].min[1]) && (array_y[p] <= recv_bbox[pk].max[1])) {
569521f74f9SMatthew G. Knepley           /* copy point into buffer */
570*9566063dSJacob Faibussowitsch           PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db,p,point_buffer));
57177048351SPatrick Sanan           /* insert point buffer into DMSwarmDataExchanger */
572*9566063dSJacob Faibussowitsch           PetscCall(DMSwarmDataExPackData(de,recv_bbox[pk].owner_rank,1,point_buffer));
573b16650c8SDave May         }
574b16650c8SDave May       }
575b16650c8SDave May     }
576*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,"coory",NULL,NULL,(void**)&array_y));
577*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,"coorx",NULL,NULL,(void**)&array_x));
578b16650c8SDave May   }
579*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
580*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
581*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
582*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
583*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExGetRecvData(de,&n_points_recv,(void**)&recv_points));
584*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
585*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db,npoints + n_points_recv,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
586b16650c8SDave May   for (p=0; p<n_points_recv; p++) {
587b16650c8SDave May     void *data_p = (void*)( (char*)recv_points + p*sizeof_dmswarm_point);
588b16650c8SDave May 
589*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db,npoints+p,data_p));
590b16650c8SDave May   }
591*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db,&point_buffer));
592b16650c8SDave May   PetscFree(bbox);
593*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExView(de));
594*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
595b16650c8SDave May   PetscFunctionReturn(0);
596b16650c8SDave May }
597a9fd7477SDave May 
598a9fd7477SDave May /* General collection when no order, or neighbour information is provided */
599a9fd7477SDave May /*
600a9fd7477SDave May  User provides context and collect() method
601a9fd7477SDave May  Broadcast user context
602a9fd7477SDave May 
603a9fd7477SDave May  for each context / rank {
604a9fd7477SDave May    collect(swarm,context,n,list)
605a9fd7477SDave May  }
606a9fd7477SDave May */
607a9fd7477SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollect_General(DM dm,PetscErrorCode (*collect)(DM,void*,PetscInt*,PetscInt**),size_t ctx_size,void *ctx,PetscInt *globalsize)
608a9fd7477SDave May {
609a9fd7477SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
61077048351SPatrick Sanan   DMSwarmDataEx  de;
611a9fd7477SDave May   PetscInt       p,r,npoints,n_points_recv;
612e4fbd051SBarry Smith   PetscMPIInt    size,rank;
613a9fd7477SDave May   void           *point_buffer,*recv_points;
614a9fd7477SDave May   void           *ctxlist;
615a9fd7477SDave May   PetscInt       *n2collect,**collectlist;
616a9fd7477SDave May   size_t         sizeof_dmswarm_point;
617a9fd7477SDave May 
618521f74f9SMatthew G. Knepley   PetscFunctionBegin;
619*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm),&size));
620*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank));
621*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
622a9fd7477SDave May   *globalsize = npoints;
623a9fd7477SDave May   /* Broadcast user context */
624e4fbd051SBarry Smith   PetscMalloc(ctx_size*size,&ctxlist);
625*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allgather(ctx,ctx_size,MPI_CHAR,ctxlist,ctx_size,MPI_CHAR,PetscObjectComm((PetscObject)dm)));
626*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&n2collect));
627*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size,&collectlist));
628e4fbd051SBarry Smith   for (r=0; r<size; r++) {
629a9fd7477SDave May     PetscInt _n2collect;
630a9fd7477SDave May     PetscInt *_collectlist;
631a9fd7477SDave May     void     *_ctx_r;
632a9fd7477SDave May 
633a9fd7477SDave May     _n2collect   = 0;
634a9fd7477SDave May     _collectlist = NULL;
635a9fd7477SDave May     if (r != rank) { /* don't collect data from yourself */
636a9fd7477SDave May       _ctx_r = (void*)( (char*)ctxlist + r * ctx_size);
637*9566063dSJacob Faibussowitsch       PetscCall(collect(dm,_ctx_r,&_n2collect,&_collectlist));
638a9fd7477SDave May     }
639a9fd7477SDave May     n2collect[r]   = _n2collect;
640a9fd7477SDave May     collectlist[r] = _collectlist;
641a9fd7477SDave May   }
642*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm),0,&de));
643a9fd7477SDave May   /* Define topology */
644*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
645e4fbd051SBarry Smith   for (r=0; r<size; r++) {
646a9fd7477SDave May     if (n2collect[r] > 0) {
647*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExTopologyAddNeighbour(de,(PetscMPIInt)r));
648a9fd7477SDave May     }
649a9fd7477SDave May   }
650*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
651a9fd7477SDave May   /* Define send counts */
652*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
653e4fbd051SBarry Smith   for (r=0; r<size; r++) {
654a9fd7477SDave May     if (n2collect[r] > 0) {
655*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExAddToSendCount(de,r,n2collect[r]));
656a9fd7477SDave May     }
657a9fd7477SDave May   }
658*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
659a9fd7477SDave May   /* Pack data */
660*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db,&sizeof_dmswarm_point,&point_buffer));
661*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de,sizeof_dmswarm_point));
662e4fbd051SBarry Smith   for (r=0; r<size; r++) {
663a9fd7477SDave May     for (p=0; p<n2collect[r]; p++) {
664*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db,collectlist[r][p],point_buffer));
665a9fd7477SDave May       /* insert point buffer into the data exchanger */
666*9566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de,r,1,point_buffer));
667a9fd7477SDave May     }
668a9fd7477SDave May   }
669*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
670a9fd7477SDave May   /* Scatter */
671*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
672*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
673a9fd7477SDave May   /* Collect data in DMSwarm container */
674*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExGetRecvData(de,&n_points_recv,(void**)&recv_points));
675*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL));
676*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db,npoints + n_points_recv,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
677a9fd7477SDave May   for (p=0; p<n_points_recv; p++) {
678a9fd7477SDave May     void *data_p = (void*)( (char*)recv_points + p*sizeof_dmswarm_point);
679a9fd7477SDave May 
680*9566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db,npoints+p,data_p));
681a9fd7477SDave May   }
682a9fd7477SDave May   /* Release memory */
683e4fbd051SBarry Smith   for (r=0; r<size; r++) {
684a9fd7477SDave May     if (collectlist[r]) PetscFree(collectlist[r]);
685a9fd7477SDave May   }
686*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(collectlist));
687*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(n2collect));
688*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(ctxlist));
689*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db,&point_buffer));
690*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExView(de));
691*9566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
692a9fd7477SDave May   PetscFunctionReturn(0);
693a9fd7477SDave May }
694