xref: /petsc/src/dm/impls/swarm/swarm_migrate.c (revision 19307e5cf369b208f3c5d721c42c941e418b5101)
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
106497c311SBarry Smith 
116497c311SBarry Smith  It should be storing the rank information as MPIInt not Int
12480eef7bSDave May */
13d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate_Push_Basic(DM dm, PetscBool remove_sent_points)
14d71ae5a4SJacob Faibussowitsch {
15df21e3a8SDave May   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
1677048351SPatrick Sanan   DMSwarmDataEx de;
17df21e3a8SDave May   PetscInt      p, npoints, *rankval, n_points_recv;
18df21e3a8SDave May   PetscMPIInt   rank, nrank;
19df21e3a8SDave May   void         *point_buffer, *recv_points;
20df21e3a8SDave May   size_t        sizeof_dmswarm_point;
21356ed814SMatthew G. Knepley   PetscBool     debug = PETSC_FALSE;
22df21e3a8SDave May 
23521f74f9SMatthew G. Knepley   PetscFunctionBegin;
249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
25df21e3a8SDave May 
269566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
279566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
289566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm), 0, &de));
299566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
30521f74f9SMatthew G. Knepley   for (p = 0; p < npoints; ++p) {
31835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(rankval[p], &nrank));
3248a46eb9SPierre Jolivet     if (nrank != rank) PetscCall(DMSwarmDataExTopologyAddNeighbour(de, nrank));
33df21e3a8SDave May   }
349566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
359566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
36df21e3a8SDave May   for (p = 0; p < npoints; p++) {
37835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(rankval[p], &nrank));
3848a46eb9SPierre Jolivet     if (nrank != rank) PetscCall(DMSwarmDataExAddToSendCount(de, nrank, 1));
39df21e3a8SDave May   }
409566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
419566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db, &sizeof_dmswarm_point, &point_buffer));
429566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de, sizeof_dmswarm_point));
43df21e3a8SDave May   for (p = 0; p < npoints; p++) {
44835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(rankval[p], &nrank));
45df21e3a8SDave May     if (nrank != rank) {
46df21e3a8SDave May       /* copy point into buffer */
479566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db, p, point_buffer));
4877048351SPatrick Sanan       /* insert point buffer into DMSwarmDataExchanger */
499566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de, nrank, 1, point_buffer));
50df21e3a8SDave May     }
51df21e3a8SDave May   }
529566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
539566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
54df21e3a8SDave May 
55df21e3a8SDave May   if (remove_sent_points) {
5677048351SPatrick Sanan     DMSwarmDataField gfield;
5722a417f9SDave May 
589566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, DMSwarmField_rank, &gfield));
599566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetAccess(gfield));
609566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetEntries(gfield, (void **)&rankval));
6122a417f9SDave May 
62df21e3a8SDave May     /* remove points which left processor */
639566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
64df21e3a8SDave May     for (p = 0; p < npoints; p++) {
65835f2295SStefano Zampini       PetscCall(PetscMPIIntCast(rankval[p], &nrank));
66df21e3a8SDave May       if (nrank != rank) {
67df21e3a8SDave May         /* kill point */
689566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
6922a417f9SDave May 
709566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, p));
7122a417f9SDave May 
729566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL)); /* you need to update npoints as the list size decreases! */
739566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetAccess(gfield));
749566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetEntries(gfield, (void **)&rankval));
75df21e3a8SDave May         p--; /* check replacement point */
76df21e3a8SDave May       }
77df21e3a8SDave May     }
789566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldRestoreEntries(gfield, (void **)&rankval));
799566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
80df21e3a8SDave May   }
819566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
829566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
83835f2295SStefano Zampini   PetscCall(DMSwarmDataExGetRecvData(de, &n_points_recv, &recv_points));
849566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
859566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, npoints + n_points_recv, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
86df21e3a8SDave May   for (p = 0; p < n_points_recv; p++) {
87df21e3a8SDave May     void *data_p = (void *)((char *)recv_points + p * sizeof_dmswarm_point);
88df21e3a8SDave May 
899566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db, npoints + p, data_p));
90df21e3a8SDave May   }
91356ed814SMatthew G. Knepley   if (debug) PetscCall(DMSwarmDataExView(de));
929566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db, &point_buffer));
939566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95df21e3a8SDave May }
962712d1f2SDave May 
9766976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmMigrate_DMNeighborScatter(DM dm, DM dmcell, PetscBool remove_sent_points, PetscInt *npoints_prior_migration)
98d71ae5a4SJacob Faibussowitsch {
9940c453e9SDave May   DM_Swarm          *swarm = (DM_Swarm *)dm->data;
100*19307e5cSMatthew G. Knepley   DMSwarmCellDM      celldm;
10177048351SPatrick Sanan   DMSwarmDataEx      de;
1021f70fafbSZach Atkins   PetscInt           r, p, npoints, *p_cellid, 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;
109*19307e5cSMatthew G. Knepley   const char        *cellid;
11040c453e9SDave May 
111521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1139566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
114*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
115*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCellID(celldm, &cellid));
116*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&p_cellid));
1179566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm), 0, &de));
1189566063dSJacob Faibussowitsch   PetscCall(DMGetNeighbors(dmcell, &nneighbors, &neighbourranks));
1199566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
12040c453e9SDave May   for (r = 0; r < nneighbors; r++) {
12140c453e9SDave May     _rank = neighbourranks[r];
12248a46eb9SPierre Jolivet     if ((_rank != rank) && (_rank > 0)) PetscCall(DMSwarmDataExTopologyAddNeighbour(de, _rank));
12340c453e9SDave May   }
1249566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
1259566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyGetNeighbours(de, &mynneigh, &myneigh));
1269566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
12740c453e9SDave May   for (p = 0; p < npoints; p++) {
1281f70fafbSZach Atkins     if (p_cellid[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
1297c6d1d28SDave May       for (r = 0; r < mynneigh; r++) {
1307c6d1d28SDave May         _rank = myneigh[r];
1319566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataExAddToSendCount(de, _rank, 1));
13240c453e9SDave May       }
13340c453e9SDave May     }
13440c453e9SDave May   }
1359566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
1369566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db, &sizeof_dmswarm_point, &point_buffer));
1379566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de, sizeof_dmswarm_point));
13840c453e9SDave May   for (p = 0; p < npoints; p++) {
1391f70fafbSZach Atkins     if (p_cellid[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
1407c6d1d28SDave May       for (r = 0; r < mynneigh; r++) {
1417c6d1d28SDave May         _rank = myneigh[r];
14240c453e9SDave May         /* copy point into buffer */
1439566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db, p, point_buffer));
14477048351SPatrick Sanan         /* insert point buffer into DMSwarmDataExchanger */
1459566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataExPackData(de, _rank, 1, point_buffer));
14640c453e9SDave May       }
14740c453e9SDave May     }
14840c453e9SDave May   }
1499566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
150*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&p_cellid));
15140c453e9SDave May   if (remove_sent_points) {
15277048351SPatrick Sanan     DMSwarmDataField PField;
1537c6d1d28SDave May 
154*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, cellid, &PField));
1551f70fafbSZach Atkins     PetscCall(DMSwarmDataFieldGetEntries(PField, (void **)&p_cellid));
15640c453e9SDave May     /* remove points which left processor */
1579566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
15840c453e9SDave May     for (p = 0; p < npoints; p++) {
1591f70fafbSZach Atkins       if (p_cellid[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
16040c453e9SDave May         /* kill point */
1619566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, p));
1629566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL)); /* you need to update npoints as the list size decreases! */
1631f70fafbSZach Atkins         PetscCall(DMSwarmDataFieldGetEntries(PField, (void **)&p_cellid));     /* update date point increase realloc performed */
16440c453e9SDave May         p--;                                                                   /* check replacement point */
16540c453e9SDave May       }
16640c453e9SDave May     }
16740c453e9SDave May   }
1689566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, npoints_prior_migration, NULL, NULL));
1699566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
1709566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
171835f2295SStefano Zampini   PetscCall(DMSwarmDataExGetRecvData(de, &n_points_recv, &recv_points));
1729566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
1739566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, npoints + n_points_recv, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
17440c453e9SDave May   for (p = 0; p < n_points_recv; p++) {
17540c453e9SDave May     void *data_p = (void *)((char *)recv_points + p * sizeof_dmswarm_point);
17640c453e9SDave May 
1779566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db, npoints + p, data_p));
17840c453e9SDave May   }
1799566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db, &point_buffer));
1809566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
1813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18240c453e9SDave May }
183480eef7bSDave May 
184d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate_CellDMScatter(DM dm, PetscBool remove_sent_points)
185d71ae5a4SJacob Faibussowitsch {
186480eef7bSDave May   DM_Swarm          *swarm = (DM_Swarm *)dm->data;
187*19307e5cSMatthew G. Knepley   DMSwarmCellDM      celldm;
188*19307e5cSMatthew G. Knepley   PetscInt           p, npoints, npointsg = 0, npoints2, npoints2g, *rankval, *p_cellid, npoints_prior_migration, Nfc;
189bbe8250bSMatthew G. Knepley   PetscSF            sfcell = NULL;
190dfc14de9SMatthew G. Knepley   const PetscSFNode *LA_sfcell;
191480eef7bSDave May   DM                 dmcell;
192480eef7bSDave May   Vec                pos;
19340c453e9SDave May   PetscBool          error_check = swarm->migrate_error_on_missing_point;
194*19307e5cSMatthew G. Knepley   const char       **coordFields;
195e4fbd051SBarry Smith   PetscMPIInt        size, rank;
196*19307e5cSMatthew G. Knepley   const char        *cellid;
197480eef7bSDave May 
198521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1999566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &dmcell));
20028b400f6SJacob Faibussowitsch   PetscCheck(dmcell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid if cell DM provided");
201*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
202*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCellID(celldm, &cellid));
203480eef7bSDave May 
2049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
2059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
2067c6d1d28SDave May 
20743a82f2bSDave May #if 1
20843a82f2bSDave May   {
20943a82f2bSDave May     PetscInt     npoints_curr, range = 0;
21043a82f2bSDave May     PetscSFNode *sf_cells;
21143a82f2bSDave May 
2129566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints_curr, NULL, NULL));
2139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(npoints_curr, &sf_cells));
21443a82f2bSDave May 
215*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&p_cellid));
21643a82f2bSDave May     for (p = 0; p < npoints_curr; p++) {
21743a82f2bSDave May       sf_cells[p].rank  = 0;
21843a82f2bSDave May       sf_cells[p].index = p_cellid[p];
219ad540459SPierre Jolivet       if (p_cellid[p] > range) range = p_cellid[p];
22043a82f2bSDave May     }
221*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&p_cellid));
22243a82f2bSDave May 
2239566063dSJacob Faibussowitsch     /* PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm),&sfcell)); */
2249566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sfcell));
2259566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfcell, range, npoints_curr, NULL, PETSC_OWN_POINTER, sf_cells, PETSC_OWN_POINTER));
22643a82f2bSDave May   }
22743a82f2bSDave May #endif
22843a82f2bSDave May 
229*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
230*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateLocalVectorFromFields(dm, Nfc, coordFields, &pos));
2319566063dSJacob Faibussowitsch   PetscCall(DMLocatePoints(dmcell, pos, DM_POINTLOCATION_NONE, &sfcell));
232*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyLocalVectorFromFields(dm, Nfc, coordFields, &pos));
233480eef7bSDave May 
23448a46eb9SPierre Jolivet   if (error_check) PetscCall(DMSwarmGetSize(dm, &npointsg));
2359566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
236*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&p_cellid));
2379566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
2389566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell));
2391f70fafbSZach Atkins 
2401f70fafbSZach Atkins   for (p = 0; p < npoints; p++) {
2411f70fafbSZach Atkins     p_cellid[p] = LA_sfcell[p].index;
2421f70fafbSZach Atkins     rankval[p]  = rank;
2431f70fafbSZach Atkins   }
2449566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
245*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&p_cellid));
2469566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfcell));
247480eef7bSDave May 
248e4fbd051SBarry Smith   if (size > 1) {
2499566063dSJacob Faibussowitsch     PetscCall(DMSwarmMigrate_DMNeighborScatter(dm, dmcell, remove_sent_points, &npoints_prior_migration));
2506fbf25f8SDave May   } else {
25177048351SPatrick Sanan     DMSwarmDataField PField;
2520ed23c7fSDave May     PetscInt         npoints_curr;
2530ed23c7fSDave May 
2540ed23c7fSDave May     /* remove points which the domain */
255*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, cellid, &PField));
2561f70fafbSZach Atkins     PetscCall(DMSwarmDataFieldGetEntries(PField, (void **)&p_cellid));
2570ed23c7fSDave May 
2589566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints_curr, NULL, NULL));
2590ed23c7fSDave May     for (p = 0; p < npoints_curr; p++) {
2601f70fafbSZach Atkins       if (p_cellid[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
2610ed23c7fSDave May         /* kill point */
2629566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, p));
2639566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints_curr, NULL, NULL)); /* you need to update npoints as the list size decreases! */
2641f70fafbSZach Atkins         PetscCall(DMSwarmDataFieldGetEntries(PField, (void **)&p_cellid));          /* update date point in case realloc performed */
2650ed23c7fSDave May         p--;                                                                        /* check replacement point */
2660ed23c7fSDave May       }
2670ed23c7fSDave May     }
2681f70fafbSZach Atkins     PetscCall(DMSwarmGetLocalSize(dm, &npoints_prior_migration));
2696fbf25f8SDave May   }
270480eef7bSDave May 
2712d4ee042Sprj-   /* locate points newly received */
2729566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints2, NULL, NULL));
273009b43efSDave May 
2747c6d1d28SDave May #if 0
2752d4ee042Sprj-   { /* safe alternative - however this performs two point locations on: (i) the initial points set and; (ii) the (initial + received) point set */
2767c6d1d28SDave May     PetscScalar *LA_coor;
2777c6d1d28SDave May     PetscInt bs;
27877048351SPatrick Sanan     DMSwarmDataField PField;
2797c6d1d28SDave May 
280d52c2f21SMatthew G. Knepley     PetscCall(DMSwarmGetField(dm,coordname,&bs,NULL,(void**)&LA_coor));
2819566063dSJacob Faibussowitsch     PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,bs,bs*npoints2,(const PetscScalar*)LA_coor,&pos));
2829566063dSJacob Faibussowitsch     PetscCall(DMLocatePoints(dmcell,pos,DM_POINTLOCATION_NONE,&sfcell));
2837c6d1d28SDave May 
2849566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&pos));
285d52c2f21SMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm,coordname,&bs,NULL,(void**)&LA_coor));
2867c6d1d28SDave May 
2879566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell));
2889566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
2897c6d1d28SDave May     for (p=0; p<npoints2; p++) {
290dfc14de9SMatthew G. Knepley       rankval[p] = LA_sfcell[p].index;
2917c6d1d28SDave May     }
2929566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfcell));
2939566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval));
29440c453e9SDave May 
2957c6d1d28SDave May     /* remove points which left processor */
2969566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,DMSwarmField_rank,&PField));
2979566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval));
2987c6d1d28SDave May 
2999566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL));
3007c6d1d28SDave May     for (p=0; p<npoints2; p++) {
301f954cb40SDave May       if (rankval[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
3027c6d1d28SDave May         /* kill point */
3039566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db,p));
3049566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db,&npoints2,NULL,NULL)); /* you need to update npoints as the list size decreases! */
3059566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataFieldGetEntries(PField,(void**)&rankval)); /* update date point increase realloc performed */
3067c6d1d28SDave May         p--; /* check replacement point */
3077c6d1d28SDave May       }
3087c6d1d28SDave May     }
30940c453e9SDave May   }
310009b43efSDave May #endif
311009b43efSDave May 
3125627991aSBarry Smith   { /* perform two point locations: (i) on the initial points set prior to communication; and (ii) on the new (received) points */
313*19307e5cSMatthew G. Knepley     Vec              npos;
314*19307e5cSMatthew G. Knepley     IS               nis;
315009b43efSDave May     PetscInt         npoints_from_neighbours, bs;
31677048351SPatrick Sanan     DMSwarmDataField PField;
317009b43efSDave May 
318009b43efSDave May     npoints_from_neighbours = npoints2 - npoints_prior_migration;
319009b43efSDave May 
320*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmCreateLocalVectorFromFields(dm, Nfc, coordFields, &pos));
321*19307e5cSMatthew G. Knepley     PetscCall(VecGetBlockSize(pos, &bs));
322*19307e5cSMatthew G. Knepley     PetscCall(ISCreateStride(PETSC_COMM_SELF, npoints_from_neighbours * bs, npoints_prior_migration * bs, 1, &nis));
323*19307e5cSMatthew G. Knepley     PetscCall(VecGetSubVector(pos, nis, &npos));
324*19307e5cSMatthew G. Knepley     PetscCall(DMLocatePoints(dmcell, npos, DM_POINTLOCATION_NONE, &sfcell));
325*19307e5cSMatthew G. Knepley     PetscCall(VecRestoreSubVector(pos, nis, &npos));
326*19307e5cSMatthew G. Knepley     PetscCall(ISDestroy(&nis));
327*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmDestroyLocalVectorFromFields(dm, Nfc, coordFields, &pos));
328009b43efSDave May 
3299566063dSJacob Faibussowitsch     PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell));
3309566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
331*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&p_cellid));
3321f70fafbSZach Atkins     for (p = 0; p < npoints_from_neighbours; p++) {
3331f70fafbSZach Atkins       rankval[npoints_prior_migration + p]  = rank;
3341f70fafbSZach Atkins       p_cellid[npoints_prior_migration + p] = LA_sfcell[p].index;
3351f70fafbSZach Atkins     }
3361f70fafbSZach Atkins 
337*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&p_cellid));
3389566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
3399566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfcell));
340009b43efSDave May 
341009b43efSDave May     /* remove points which left processor */
342*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, cellid, &PField));
3431f70fafbSZach Atkins     PetscCall(DMSwarmDataFieldGetEntries(PField, (void **)&p_cellid));
344009b43efSDave May 
3459566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints2, NULL, NULL));
346009b43efSDave May     for (p = npoints_prior_migration; p < npoints2; p++) {
3471f70fafbSZach Atkins       if (p_cellid[p] == DMLOCATEPOINT_POINT_NOT_FOUND) {
348009b43efSDave May         /* kill point */
3499566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, p));
3509566063dSJacob Faibussowitsch         PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints2, NULL, NULL)); /* you need to update npoints as the list size decreases! */
3511f70fafbSZach Atkins         PetscCall(DMSwarmDataFieldGetEntries(PField, (void **)&p_cellid));      /* update date point in case realloc performed */
352009b43efSDave May         p--;                                                                    /* check replacement point */
353009b43efSDave May       }
354009b43efSDave May     }
355009b43efSDave May   }
356009b43efSDave May 
35740c453e9SDave May   /* check for error on removed points */
35840c453e9SDave May   if (error_check) {
3599566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetSize(dm, &npoints2g));
36063a3b9bcSJacob Faibussowitsch     PetscCheck(npointsg == npoints2g, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Points from the DMSwarm must remain constant during migration (initial %" PetscInt_FMT " - final %" PetscInt_FMT ")", npointsg, npoints2g);
36140c453e9SDave May   }
3623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
363480eef7bSDave May }
364480eef7bSDave May 
365d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate_CellDMExact(DM dm, PetscBool remove_sent_points)
366d71ae5a4SJacob Faibussowitsch {
367521f74f9SMatthew G. Knepley   PetscFunctionBegin;
3683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36908056efcSDave May }
37008056efcSDave May 
371480eef7bSDave May /*
372480eef7bSDave May  Redundant as this assumes points can only be sent to a single rank
373480eef7bSDave May */
374d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize)
375d71ae5a4SJacob Faibussowitsch {
3762712d1f2SDave May   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
37777048351SPatrick Sanan   DMSwarmDataEx de;
3782712d1f2SDave May   PetscInt      p, npoints, *rankval, n_points_recv;
3792712d1f2SDave May   PetscMPIInt   rank, nrank, negrank;
3802712d1f2SDave May   void         *point_buffer, *recv_points;
3812712d1f2SDave May   size_t        sizeof_dmswarm_point;
3822712d1f2SDave May 
383521f74f9SMatthew G. Knepley   PetscFunctionBegin;
3849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
3859566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
3862712d1f2SDave May   *globalsize = npoints;
3879566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
3889566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm), 0, &de));
3899566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
3902712d1f2SDave May   for (p = 0; p < npoints; p++) {
391835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(rankval[p], &negrank));
3922712d1f2SDave May     if (negrank < 0) {
3932712d1f2SDave May       nrank = -negrank - 1;
3949566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExTopologyAddNeighbour(de, nrank));
3952712d1f2SDave May     }
3962712d1f2SDave May   }
3979566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
3989566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
3992712d1f2SDave May   for (p = 0; p < npoints; p++) {
400835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(rankval[p], &negrank));
4012712d1f2SDave May     if (negrank < 0) {
4022712d1f2SDave May       nrank = -negrank - 1;
4039566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExAddToSendCount(de, nrank, 1));
4042712d1f2SDave May     }
4052712d1f2SDave May   }
4069566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
4079566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db, &sizeof_dmswarm_point, &point_buffer));
4089566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de, sizeof_dmswarm_point));
4092712d1f2SDave May   for (p = 0; p < npoints; p++) {
410835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(rankval[p], &negrank));
4112712d1f2SDave May     if (negrank < 0) {
4122712d1f2SDave May       nrank      = -negrank - 1;
4132712d1f2SDave May       rankval[p] = nrank;
4142712d1f2SDave May       /* copy point into buffer */
4159566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db, p, point_buffer));
41677048351SPatrick Sanan       /* insert point buffer into DMSwarmDataExchanger */
4179566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de, nrank, 1, point_buffer));
4182712d1f2SDave May       rankval[p] = negrank;
4192712d1f2SDave May     }
4202712d1f2SDave May   }
4219566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
4229566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
4239566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
4249566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
425835f2295SStefano Zampini   PetscCall(DMSwarmDataExGetRecvData(de, &n_points_recv, &recv_points));
4269566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
4279566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, npoints + n_points_recv, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
4282712d1f2SDave May   for (p = 0; p < n_points_recv; p++) {
4292712d1f2SDave May     void *data_p = (void *)((char *)recv_points + p * sizeof_dmswarm_point);
4302712d1f2SDave May 
4319566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db, npoints + p, data_p));
4322712d1f2SDave May   }
4339566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExView(de));
4349566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db, &point_buffer));
4359566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
4363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4372712d1f2SDave May }
438b16650c8SDave May 
439b16650c8SDave May typedef struct {
440b16650c8SDave May   PetscMPIInt owner_rank;
441b16650c8SDave May   PetscReal   min[3], max[3];
442b16650c8SDave May } CollectBBox;
443b16650c8SDave May 
444d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmCollect_DMDABoundingBox(DM dm, PetscInt *globalsize)
445d71ae5a4SJacob Faibussowitsch {
446b16650c8SDave May   DM_Swarm          *swarm = (DM_Swarm *)dm->data;
44777048351SPatrick Sanan   DMSwarmDataEx      de;
448b16650c8SDave May   PetscInt           p, pk, npoints, *rankval, n_points_recv, n_bbox_recv, dim, neighbour_cells;
449b16650c8SDave May   PetscMPIInt        rank, nrank;
450b16650c8SDave May   void              *point_buffer, *recv_points;
451b16650c8SDave May   size_t             sizeof_dmswarm_point, sizeof_bbox_ctx;
452b16650c8SDave May   PetscBool          isdmda;
453b16650c8SDave May   CollectBBox       *bbox, *recv_bbox;
454b16650c8SDave May   const PetscMPIInt *dmneighborranks;
455b16650c8SDave May   DM                 dmcell;
456b16650c8SDave May 
457521f74f9SMatthew G. Knepley   PetscFunctionBegin;
4589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
459b16650c8SDave May 
4609566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &dmcell));
46128b400f6SJacob Faibussowitsch   PetscCheck(dmcell, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid if cell DM provided");
462b16650c8SDave May   isdmda = PETSC_FALSE;
4633ba16761SJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)dmcell, DMDA, &isdmda));
46428b400f6SJacob Faibussowitsch   PetscCheck(isdmda, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only DMDA support for CollectBoundingBox");
465b16650c8SDave May 
4669566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
467b16650c8SDave May   sizeof_bbox_ctx = sizeof(CollectBBox);
4683ba16761SJacob Faibussowitsch   PetscCall(PetscMalloc1(1, &bbox));
469b16650c8SDave May   bbox->owner_rank = rank;
470b16650c8SDave May 
471b16650c8SDave May   /* compute the bounding box based on the overlapping / stenctil size */
472b16650c8SDave May   {
473b16650c8SDave May     Vec lcoor;
474b16650c8SDave May 
4759566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dmcell, &lcoor));
476fe39f135SDave May     if (dim >= 1) {
4779566063dSJacob Faibussowitsch       PetscCall(VecStrideMin(lcoor, 0, NULL, &bbox->min[0]));
4789566063dSJacob Faibussowitsch       PetscCall(VecStrideMax(lcoor, 0, NULL, &bbox->max[0]));
479fe39f135SDave May     }
480fe39f135SDave May     if (dim >= 2) {
4819566063dSJacob Faibussowitsch       PetscCall(VecStrideMin(lcoor, 1, NULL, &bbox->min[1]));
4829566063dSJacob Faibussowitsch       PetscCall(VecStrideMax(lcoor, 1, NULL, &bbox->max[1]));
483b16650c8SDave May     }
484fe39f135SDave May     if (dim == 3) {
4859566063dSJacob Faibussowitsch       PetscCall(VecStrideMin(lcoor, 2, NULL, &bbox->min[2]));
4869566063dSJacob Faibussowitsch       PetscCall(VecStrideMax(lcoor, 2, NULL, &bbox->max[2]));
487fe39f135SDave May     }
488fe39f135SDave May   }
4899566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
490b16650c8SDave May   *globalsize = npoints;
4919566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
4929566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm), 0, &de));
493b16650c8SDave May   /* use DMDA neighbours */
4949566063dSJacob Faibussowitsch   PetscCall(DMDAGetNeighbors(dmcell, &dmneighborranks));
4958dbd68bcSDave May   if (dim == 1) {
4968dbd68bcSDave May     neighbour_cells = 3;
4978dbd68bcSDave May   } else if (dim == 2) {
4988dbd68bcSDave May     neighbour_cells = 9;
4998dbd68bcSDave May   } else {
5008dbd68bcSDave May     neighbour_cells = 27;
5018dbd68bcSDave May   }
5029566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
503b16650c8SDave May   for (p = 0; p < neighbour_cells; p++) {
50448a46eb9SPierre Jolivet     if ((dmneighborranks[p] >= 0) && (dmneighborranks[p] != rank)) PetscCall(DMSwarmDataExTopologyAddNeighbour(de, dmneighborranks[p]));
505b16650c8SDave May   }
5069566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
5079566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
508b16650c8SDave May   for (p = 0; p < neighbour_cells; p++) {
50948a46eb9SPierre Jolivet     if ((dmneighborranks[p] >= 0) && (dmneighborranks[p] != rank)) PetscCall(DMSwarmDataExAddToSendCount(de, dmneighborranks[p], 1));
510b16650c8SDave May   }
5119566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
512b16650c8SDave May   /* send bounding boxes */
5139566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de, sizeof_bbox_ctx));
514b16650c8SDave May   for (p = 0; p < neighbour_cells; p++) {
515b16650c8SDave May     nrank = dmneighborranks[p];
516b16650c8SDave May     if ((nrank >= 0) && (nrank != rank)) {
51777048351SPatrick Sanan       /* insert bbox buffer into DMSwarmDataExchanger */
5189566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de, nrank, 1, bbox));
519b16650c8SDave May     }
520b16650c8SDave May   }
5219566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
522b16650c8SDave May   /* recv bounding boxes */
5239566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
5249566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
5259566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExGetRecvData(de, &n_bbox_recv, (void **)&recv_bbox));
526298827fbSBarry Smith   /*  Wrong, should not be using PETSC_COMM_WORLD */
527b16650c8SDave May   for (p = 0; p < n_bbox_recv; p++) {
5289371c9d4SSatish Balay     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, (double)recv_bbox[p].min[0], (double)recv_bbox[p].max[0], (double)recv_bbox[p].min[1],
5299371c9d4SSatish Balay                                       (double)recv_bbox[p].max[1]));
530b16650c8SDave May   }
5319566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, stdout));
532b16650c8SDave May   /* of course this is stupid as this "generic" function should have a better way to know what the coordinates are called */
5339566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
534b16650c8SDave May   for (pk = 0; pk < n_bbox_recv; pk++) {
535b16650c8SDave May     PetscReal *array_x, *array_y;
536b16650c8SDave May 
5379566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm, "coorx", NULL, NULL, (void **)&array_x));
5389566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm, "coory", NULL, NULL, (void **)&array_y));
539b16650c8SDave May     for (p = 0; p < npoints; p++) {
540b16650c8SDave May       if ((array_x[p] >= recv_bbox[pk].min[0]) && (array_x[p] <= recv_bbox[pk].max[0])) {
54148a46eb9SPierre Jolivet         if ((array_y[p] >= recv_bbox[pk].min[1]) && (array_y[p] <= recv_bbox[pk].max[1])) PetscCall(DMSwarmDataExAddToSendCount(de, recv_bbox[pk].owner_rank, 1));
542b16650c8SDave May       }
543b16650c8SDave May     }
5449566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm, "coory", NULL, NULL, (void **)&array_y));
5459566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm, "coorx", NULL, NULL, (void **)&array_x));
546b16650c8SDave May   }
5479566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
5489566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db, &sizeof_dmswarm_point, &point_buffer));
5499566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de, sizeof_dmswarm_point));
550b16650c8SDave May   for (pk = 0; pk < n_bbox_recv; pk++) {
551b16650c8SDave May     PetscReal *array_x, *array_y;
552b16650c8SDave May 
5539566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm, "coorx", NULL, NULL, (void **)&array_x));
5549566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dm, "coory", NULL, NULL, (void **)&array_y));
555b16650c8SDave May     for (p = 0; p < npoints; p++) {
556b16650c8SDave May       if ((array_x[p] >= recv_bbox[pk].min[0]) && (array_x[p] <= recv_bbox[pk].max[0])) {
557b16650c8SDave May         if ((array_y[p] >= recv_bbox[pk].min[1]) && (array_y[p] <= recv_bbox[pk].max[1])) {
558521f74f9SMatthew G. Knepley           /* copy point into buffer */
5599566063dSJacob Faibussowitsch           PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db, p, point_buffer));
56077048351SPatrick Sanan           /* insert point buffer into DMSwarmDataExchanger */
5619566063dSJacob Faibussowitsch           PetscCall(DMSwarmDataExPackData(de, recv_bbox[pk].owner_rank, 1, point_buffer));
562b16650c8SDave May         }
563b16650c8SDave May       }
564b16650c8SDave May     }
5659566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm, "coory", NULL, NULL, (void **)&array_y));
5669566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dm, "coorx", NULL, NULL, (void **)&array_x));
567b16650c8SDave May   }
5689566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
5699566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
5709566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
5719566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
572835f2295SStefano Zampini   PetscCall(DMSwarmDataExGetRecvData(de, &n_points_recv, &recv_points));
5739566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
5749566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, npoints + n_points_recv, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
575b16650c8SDave May   for (p = 0; p < n_points_recv; p++) {
576b16650c8SDave May     void *data_p = (void *)((char *)recv_points + p * sizeof_dmswarm_point);
577b16650c8SDave May 
5789566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db, npoints + p, data_p));
579b16650c8SDave May   }
5809566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db, &point_buffer));
581e57ab8abSSatish Balay   PetscCall(PetscFree(bbox));
5829566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExView(de));
5839566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
5843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
585b16650c8SDave May }
586a9fd7477SDave May 
587a9fd7477SDave May /* General collection when no order, or neighbour information is provided */
588a9fd7477SDave May /*
589a9fd7477SDave May  User provides context and collect() method
590a9fd7477SDave May  Broadcast user context
591a9fd7477SDave May 
592a9fd7477SDave May  for each context / rank {
593a9fd7477SDave May    collect(swarm,context,n,list)
594a9fd7477SDave May  }
595a9fd7477SDave May */
596d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmCollect_General(DM dm, PetscErrorCode (*collect)(DM, void *, PetscInt *, PetscInt **), size_t ctx_size, void *ctx, PetscInt *globalsize)
597d71ae5a4SJacob Faibussowitsch {
598a9fd7477SDave May   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
59977048351SPatrick Sanan   DMSwarmDataEx de;
6006497c311SBarry Smith   PetscInt      p, npoints, n_points_recv;
6016497c311SBarry Smith   PetscMPIInt   size, rank, len;
602a9fd7477SDave May   void         *point_buffer, *recv_points;
603a9fd7477SDave May   void         *ctxlist;
604a9fd7477SDave May   PetscInt     *n2collect, **collectlist;
605a9fd7477SDave May   size_t        sizeof_dmswarm_point;
606a9fd7477SDave May 
607521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
6099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
6109566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
611a9fd7477SDave May   *globalsize = npoints;
612a9fd7477SDave May   /* Broadcast user context */
6136497c311SBarry Smith   PetscCall(PetscMPIIntCast(ctx_size, &len));
6143ba16761SJacob Faibussowitsch   PetscCall(PetscMalloc(ctx_size * size, &ctxlist));
6156497c311SBarry Smith   PetscCallMPI(MPI_Allgather(ctx, len, MPI_CHAR, ctxlist, len, MPI_CHAR, PetscObjectComm((PetscObject)dm)));
6169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &n2collect));
6179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &collectlist));
6186497c311SBarry Smith   for (PetscMPIInt r = 0; r < size; r++) {
619a9fd7477SDave May     PetscInt  _n2collect;
620a9fd7477SDave May     PetscInt *_collectlist;
621a9fd7477SDave May     void     *_ctx_r;
622a9fd7477SDave May 
623a9fd7477SDave May     _n2collect   = 0;
624a9fd7477SDave May     _collectlist = NULL;
625a9fd7477SDave May     if (r != rank) { /* don't collect data from yourself */
626a9fd7477SDave May       _ctx_r = (void *)((char *)ctxlist + r * ctx_size);
6279566063dSJacob Faibussowitsch       PetscCall(collect(dm, _ctx_r, &_n2collect, &_collectlist));
628a9fd7477SDave May     }
629a9fd7477SDave May     n2collect[r]   = _n2collect;
630a9fd7477SDave May     collectlist[r] = _collectlist;
631a9fd7477SDave May   }
6329566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExCreate(PetscObjectComm((PetscObject)dm), 0, &de));
633a9fd7477SDave May   /* Define topology */
6349566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyInitialize(de));
6356497c311SBarry Smith   for (PetscMPIInt r = 0; r < size; r++) {
636835f2295SStefano Zampini     if (n2collect[r] > 0) PetscCall(DMSwarmDataExTopologyAddNeighbour(de, r));
637a9fd7477SDave May   }
6389566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExTopologyFinalize(de));
639a9fd7477SDave May   /* Define send counts */
6409566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExInitializeSendCount(de));
6416497c311SBarry Smith   for (PetscMPIInt r = 0; r < size; r++) {
64248a46eb9SPierre Jolivet     if (n2collect[r] > 0) PetscCall(DMSwarmDataExAddToSendCount(de, r, n2collect[r]));
643a9fd7477SDave May   }
6449566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExFinalizeSendCount(de));
645a9fd7477SDave May   /* Pack data */
6469566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreatePackedArray(swarm->db, &sizeof_dmswarm_point, &point_buffer));
6479566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackInitialize(de, sizeof_dmswarm_point));
6486497c311SBarry Smith   for (PetscMPIInt r = 0; r < size; r++) {
649a9fd7477SDave May     for (p = 0; p < n2collect[r]; p++) {
6509566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataBucketFillPackedArray(swarm->db, collectlist[r][p], point_buffer));
651a9fd7477SDave May       /* insert point buffer into the data exchanger */
6529566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataExPackData(de, r, 1, point_buffer));
653a9fd7477SDave May     }
654a9fd7477SDave May   }
6559566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExPackFinalize(de));
656a9fd7477SDave May   /* Scatter */
6579566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExBegin(de));
6589566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExEnd(de));
659a9fd7477SDave May   /* Collect data in DMSwarm container */
660835f2295SStefano Zampini   PetscCall(DMSwarmDataExGetRecvData(de, &n_points_recv, &recv_points));
6619566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
6629566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, npoints + n_points_recv, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
663a9fd7477SDave May   for (p = 0; p < n_points_recv; p++) {
664a9fd7477SDave May     void *data_p = (void *)((char *)recv_points + p * sizeof_dmswarm_point);
665a9fd7477SDave May 
6669566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketInsertPackedArray(swarm->db, npoints + p, data_p));
667a9fd7477SDave May   }
668a9fd7477SDave May   /* Release memory */
6696497c311SBarry Smith   for (PetscMPIInt r = 0; r < size; r++) {
670e57ab8abSSatish Balay     if (collectlist[r]) PetscCall(PetscFree(collectlist[r]));
671a9fd7477SDave May   }
6729566063dSJacob Faibussowitsch   PetscCall(PetscFree(collectlist));
6739566063dSJacob Faibussowitsch   PetscCall(PetscFree(n2collect));
6749566063dSJacob Faibussowitsch   PetscCall(PetscFree(ctxlist));
6759566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroyPackedArray(swarm->db, &point_buffer));
6769566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExView(de));
6779566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataExDestroy(de));
6783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
679a9fd7477SDave May }
68047ce4f4bSMatthew G. Knepley 
68147ce4f4bSMatthew G. Knepley /*@
68247ce4f4bSMatthew G. Knepley   DMSwarmGetMigrateType - Get the style of point migration
68347ce4f4bSMatthew G. Knepley 
68420f4b53cSBarry Smith   Logically Collective
68547ce4f4bSMatthew G. Knepley 
68660225df5SJacob Faibussowitsch   Input Parameter:
68720f4b53cSBarry Smith . dm - the `DMSWARM`
68847ce4f4bSMatthew G. Knepley 
68960225df5SJacob Faibussowitsch   Output Parameter:
69020f4b53cSBarry Smith . mtype - The migration type, see `DMSwarmMigrateType`
69147ce4f4bSMatthew G. Knepley 
69247ce4f4bSMatthew G. Knepley   Level: intermediate
69347ce4f4bSMatthew G. Knepley 
69442747ad1SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmMigrateType`, `DMSwarmMigrate()`
69547ce4f4bSMatthew G. Knepley @*/
69647ce4f4bSMatthew G. Knepley PetscErrorCode DMSwarmGetMigrateType(DM dm, DMSwarmMigrateType *mtype)
69747ce4f4bSMatthew G. Knepley {
69847ce4f4bSMatthew G. Knepley   PetscFunctionBegin;
69947ce4f4bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7004f572ea9SToby Isaac   PetscAssertPointer(mtype, 2);
70147ce4f4bSMatthew G. Knepley   *mtype = ((DM_Swarm *)dm->data)->migrate_type;
7023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70347ce4f4bSMatthew G. Knepley }
70447ce4f4bSMatthew G. Knepley 
70547ce4f4bSMatthew G. Knepley /*@
70647ce4f4bSMatthew G. Knepley   DMSwarmSetMigrateType - Set the style of point migration
70747ce4f4bSMatthew G. Knepley 
70820f4b53cSBarry Smith   Logically Collective
70947ce4f4bSMatthew G. Knepley 
71060225df5SJacob Faibussowitsch   Input Parameters:
71120f4b53cSBarry Smith + dm    - the `DMSWARM`
71220f4b53cSBarry Smith - mtype - The migration type, see `DMSwarmMigrateType`
71347ce4f4bSMatthew G. Knepley 
71447ce4f4bSMatthew G. Knepley   Level: intermediate
71547ce4f4bSMatthew G. Knepley 
71660225df5SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmMigrateType`, `DMSwarmGetMigrateType()`, `DMSwarmMigrate()`
71747ce4f4bSMatthew G. Knepley @*/
71847ce4f4bSMatthew G. Knepley PetscErrorCode DMSwarmSetMigrateType(DM dm, DMSwarmMigrateType mtype)
71947ce4f4bSMatthew G. Knepley {
72047ce4f4bSMatthew G. Knepley   PetscFunctionBegin;
72147ce4f4bSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72247ce4f4bSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, mtype, 2);
72347ce4f4bSMatthew G. Knepley   ((DM_Swarm *)dm->data)->migrate_type = mtype;
7243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
72547ce4f4bSMatthew G. Knepley }
726