xref: /petsc/src/dm/impls/swarm/swarm.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
157795646SDave May #define PETSCDM_DLL
257795646SDave May #include <petsc/private/dmswarmimpl.h> /*I   "petscdmswarm.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
40643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>
55917a6f0SStefano Zampini #include <petscviewer.h>
65917a6f0SStefano Zampini #include <petscdraw.h>
783c47955SMatthew G. Knepley #include <petscdmplex.h>
84cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h>
9279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
10d0c080abSJoseph Pusztay #include <petscdmlabel.h>
11d0c080abSJoseph Pusztay #include <petscsection.h>
1257795646SDave May 
13f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
14ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
15ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
16ed923d71SDave May 
17ea78f98cSLisandro Dalcin const char *DMSwarmTypeNames[]          = {"basic", "pic", NULL};
18ea78f98cSLisandro Dalcin const char *DMSwarmMigrateTypeNames[]   = {"basic", "dmcellnscatter", "dmcellexact", "user", NULL};
19ea78f98cSLisandro Dalcin const char *DMSwarmCollectTypeNames[]   = {"basic", "boundingbox", "general", "user", NULL};
20ea78f98cSLisandro Dalcin const char *DMSwarmPICLayoutTypeNames[] = {"regular", "gauss", "subdivision", NULL};
21f0cdbbbaSDave May 
22f0cdbbbaSDave May const char DMSwarmField_pid[]       = "DMSwarm_pid";
23f0cdbbbaSDave May const char DMSwarmField_rank[]      = "DMSwarm_rank";
24f0cdbbbaSDave May const char DMSwarmPICField_coor[]   = "DMSwarmPIC_coor";
25e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
26f0cdbbbaSDave May 
272e956fe4SStefano Zampini PetscInt SwarmDataFieldId = -1;
282e956fe4SStefano Zampini 
2974d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
3074d0cae8SMatthew G. Knepley #include <petscviewerhdf5.h>
3174d0cae8SMatthew G. Knepley 
329371c9d4SSatish Balay PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer) {
3374d0cae8SMatthew G. Knepley   DM        dm;
3474d0cae8SMatthew G. Knepley   PetscReal seqval;
3574d0cae8SMatthew G. Knepley   PetscInt  seqnum, bs;
3674d0cae8SMatthew G. Knepley   PetscBool isseq;
3774d0cae8SMatthew G. Knepley 
3874d0cae8SMatthew G. Knepley   PetscFunctionBegin;
399566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
409566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(v, &bs));
419566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields"));
429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
439566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval));
449566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
459566063dSJacob Faibussowitsch   /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */
469566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
479566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs));
489566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
4974d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
5074d0cae8SMatthew G. Knepley }
5174d0cae8SMatthew G. Knepley 
529371c9d4SSatish Balay PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer) {
5374d0cae8SMatthew G. Knepley   Vec       coordinates;
5474d0cae8SMatthew G. Knepley   PetscInt  Np;
5574d0cae8SMatthew G. Knepley   PetscBool isseq;
5674d0cae8SMatthew G. Knepley 
5774d0cae8SMatthew G. Knepley   PetscFunctionBegin;
589566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetSize(dm, &Np));
599566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates));
609566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
619566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles"));
629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq));
639566063dSJacob Faibussowitsch   PetscCall(VecViewNative(coordinates, viewer));
649566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np));
659566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
669566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates));
6774d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
6874d0cae8SMatthew G. Knepley }
6974d0cae8SMatthew G. Knepley #endif
7074d0cae8SMatthew G. Knepley 
719371c9d4SSatish Balay PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer) {
7274d0cae8SMatthew G. Knepley   DM dm;
73f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
7474d0cae8SMatthew G. Knepley   PetscBool ishdf5;
75f9558f5cSBarry Smith #endif
7674d0cae8SMatthew G. Knepley 
7774d0cae8SMatthew G. Knepley   PetscFunctionBegin;
789566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
7928b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
80f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
819566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
8274d0cae8SMatthew G. Knepley   if (ishdf5) {
839566063dSJacob Faibussowitsch     PetscCall(VecView_Swarm_HDF5_Internal(v, viewer));
84f9558f5cSBarry Smith     PetscFunctionReturn(0);
8574d0cae8SMatthew G. Knepley   }
86f9558f5cSBarry Smith #endif
879566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
8874d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
8974d0cae8SMatthew G. Knepley }
9074d0cae8SMatthew G. Knepley 
91d3a51819SDave May /*@C
9262741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
9362741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
9457795646SDave May 
95d083f849SBarry Smith    Collective on dm
9657795646SDave May 
97d3a51819SDave May    Input parameters:
9862741f57SDave May +  dm - a DMSwarm
9962741f57SDave May -  fieldname - the textual name given to a registered field
10057795646SDave May 
101d3a51819SDave May    Level: beginner
10257795646SDave May 
103d3a51819SDave May    Notes:
104e7af74c8SDave May 
10562741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
106e7af74c8SDave May 
107d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
108d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
10957795646SDave May 
110db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
111d3a51819SDave May @*/
1129371c9d4SSatish Balay PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[]) {
113b5bcf523SDave May   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
114b5bcf523SDave May   PetscInt      bs, n;
115b5bcf523SDave May   PetscScalar  *array;
116b5bcf523SDave May   PetscDataType type;
117b5bcf523SDave May 
118a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1199566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
1209566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
1219566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array));
122b5bcf523SDave May 
123b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
12408401ef6SPierre Jolivet   PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
1259566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(swarm->vec_field_name, PETSC_MAX_PATH_LEN - 1, "%s", fieldname));
126b5bcf523SDave May   swarm->vec_field_set    = PETSC_TRUE;
1271b1ea282SDave May   swarm->vec_field_bs     = bs;
128b5bcf523SDave May   swarm->vec_field_nlocal = n;
1299566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, fieldname, &bs, &type, (void **)&array));
130b5bcf523SDave May   PetscFunctionReturn(0);
131b5bcf523SDave May }
132b5bcf523SDave May 
133cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
1349371c9d4SSatish Balay PetscErrorCode DMCreateGlobalVector_Swarm(DM dm, Vec *vec) {
135b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
136b5bcf523SDave May   Vec       x;
137b5bcf523SDave May   char      name[PETSC_MAX_PATH_LEN];
138b5bcf523SDave May 
139a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1409566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
14128b400f6SJacob Faibussowitsch   PetscCheck(swarm->vec_field_set, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField first");
14208401ef6SPierre Jolivet   PetscCheck(swarm->vec_field_nlocal == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */
143cc651181SDave May 
1449566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmField_%s", swarm->vec_field_name));
1459566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &x));
1469566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
1479566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE));
1489566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(x, swarm->vec_field_bs));
1499566063dSJacob Faibussowitsch   PetscCall(VecSetDM(x, dm));
1509566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
1519566063dSJacob Faibussowitsch   PetscCall(VecSetDM(x, dm));
1529566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(x, VECOP_VIEW, (void (*)(void))VecView_Swarm));
153b5bcf523SDave May   *vec = x;
154b5bcf523SDave May   PetscFunctionReturn(0);
155b5bcf523SDave May }
156b5bcf523SDave May 
157b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
1589371c9d4SSatish Balay PetscErrorCode DMCreateLocalVector_Swarm(DM dm, Vec *vec) {
159b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
160b5bcf523SDave May   Vec       x;
161b5bcf523SDave May   char      name[PETSC_MAX_PATH_LEN];
162b5bcf523SDave May 
163a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1649566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
16528b400f6SJacob Faibussowitsch   PetscCheck(swarm->vec_field_set, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField first");
16608401ef6SPierre Jolivet   PetscCheck(swarm->vec_field_nlocal == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since last call to VectorDefineField first");
167cc651181SDave May 
1689566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmField_%s", swarm->vec_field_name));
1699566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &x));
1709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
1719566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE));
1729566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(x, swarm->vec_field_bs));
1739566063dSJacob Faibussowitsch   PetscCall(VecSetDM(x, dm));
1749566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
175b5bcf523SDave May   *vec = x;
176b5bcf523SDave May   PetscFunctionReturn(0);
177b5bcf523SDave May }
178b5bcf523SDave May 
1799371c9d4SSatish Balay static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec) {
180fb1bcc12SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
18177048351SPatrick Sanan   DMSwarmDataField gfield;
1822e956fe4SStefano Zampini   PetscInt         bs, nlocal, fid = -1, cfid = -2;
1832e956fe4SStefano Zampini   PetscBool        flg;
184d3a51819SDave May 
185fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
1862e956fe4SStefano Zampini   /* check vector is an inplace array */
1872e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
1882e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg));
1892e956fe4SStefano Zampini   PetscCheck(cfid == fid, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)! %" PetscInt_FMT " != %" PetscInt_FMT "", fieldname, cfid, fid);
1909566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(*vec, &nlocal));
1919566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(*vec, &bs));
19208401ef6SPierre Jolivet   PetscCheck(nlocal / bs == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid");
1939566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
1949566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
1958df78e51SMark Adams   PetscCall(VecResetArray(*vec));
1969566063dSJacob Faibussowitsch   PetscCall(VecDestroy(vec));
197fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
198fb1bcc12SMatthew G. Knepley }
199fb1bcc12SMatthew G. Knepley 
2009371c9d4SSatish Balay static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec) {
201fb1bcc12SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
202fb1bcc12SMatthew G. Knepley   PetscDataType type;
203fb1bcc12SMatthew G. Knepley   PetscScalar  *array;
2042e956fe4SStefano Zampini   PetscInt      bs, n, fid;
205fb1bcc12SMatthew G. Knepley   char          name[PETSC_MAX_PATH_LEN];
206e4fbd051SBarry Smith   PetscMPIInt   size;
2078df78e51SMark Adams   PetscBool     iscuda, iskokkos;
208fb1bcc12SMatthew G. Knepley 
209fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
2109566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
2119566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
2129566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array));
21308401ef6SPierre Jolivet   PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
214fb1bcc12SMatthew G. Knepley 
2159566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2168df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos));
2178df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda));
2188df78e51SMark Adams   PetscCall(VecCreate(comm, vec));
2198df78e51SMark Adams   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
2208df78e51SMark Adams   PetscCall(VecSetBlockSize(*vec, bs));
2218df78e51SMark Adams   if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS));
2228df78e51SMark Adams   else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA));
2238df78e51SMark Adams   else PetscCall(VecSetType(*vec, VECSTANDARD));
2248df78e51SMark Adams   PetscCall(VecPlaceArray(*vec, array));
2258df78e51SMark Adams 
2269566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname));
2279566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
228fb1bcc12SMatthew G. Knepley 
229fb1bcc12SMatthew G. Knepley   /* Set guard */
2302e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
2312e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid));
23274d0cae8SMatthew G. Knepley 
2339566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*vec, dm));
2349566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm));
235fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
236fb1bcc12SMatthew G. Knepley }
237fb1bcc12SMatthew G. Knepley 
2380643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
2390643ed39SMatthew G. Knepley 
2400643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
2410643ed39SMatthew G. Knepley 
2420643ed39SMatthew G. Knepley    and a particle function is given by
2430643ed39SMatthew G. Knepley 
2440643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
2450643ed39SMatthew G. Knepley 
2460643ed39SMatthew G. Knepley    then we want to require that
2470643ed39SMatthew G. Knepley 
2480643ed39SMatthew G. Knepley      M \hat f = M_p f
2490643ed39SMatthew G. Knepley 
2500643ed39SMatthew G. Knepley    where the particle mass matrix is given by
2510643ed39SMatthew G. Knepley 
2520643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
2530643ed39SMatthew G. Knepley 
2540643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
2550643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
2560643ed39SMatthew G. Knepley */
2579371c9d4SSatish Balay static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) {
25883c47955SMatthew G. Knepley   const char  *name = "Mass Matrix";
2590643ed39SMatthew G. Knepley   MPI_Comm     comm;
26083c47955SMatthew G. Knepley   PetscDS      prob;
26183c47955SMatthew G. Knepley   PetscSection fsection, globalFSection;
262e8f14785SLisandro Dalcin   PetscHSetIJ  ht;
2630643ed39SMatthew G. Knepley   PetscLayout  rLayout, colLayout;
26483c47955SMatthew G. Knepley   PetscInt    *dnz, *onz;
265adb2528bSMark Adams   PetscInt     locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
2660643ed39SMatthew G. Knepley   PetscReal   *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
26783c47955SMatthew G. Knepley   PetscScalar *elemMat;
2680643ed39SMatthew G. Knepley   PetscInt     dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
26983c47955SMatthew G. Knepley 
27083c47955SMatthew G. Knepley   PetscFunctionBegin;
2719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
2729566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &dim));
2739566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
2749566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
2759566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
2769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ));
2779566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
2789566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
2799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
2809566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
28183c47955SMatthew G. Knepley 
2829566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
2839566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
2849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
2859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
2869566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
2879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
2880643ed39SMatthew G. Knepley 
2899566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
2909566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
2919566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
2929566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
2939566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
2949566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
2950643ed39SMatthew G. Knepley 
2969566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
2979566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
29853e60ab4SJoseph Pusztay 
2999566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
3000643ed39SMatthew G. Knepley   /* count non-zeros */
3019566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
30283c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
30383c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
3040643ed39SMatthew G. Knepley       PetscInt  c, i;
3050643ed39SMatthew G. Knepley       PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */
30683c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
30783c47955SMatthew G. Knepley 
3089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3099566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
310fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
31183c47955SMatthew G. Knepley       {
312e8f14785SLisandro Dalcin         PetscHashIJKey key;
313e8f14785SLisandro Dalcin         PetscBool      missing;
31483c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
315adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
316adb2528bSMark Adams           if (key.j >= 0) {
31783c47955SMatthew G. Knepley             /* Get indices for coarse elements */
31883c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
319adb2528bSMark Adams               key.i = cindices[c] + rStart; /* global cols (from Swarm) */
320adb2528bSMark Adams               if (key.i < 0) continue;
3219566063dSJacob Faibussowitsch               PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
32283c47955SMatthew G. Knepley               if (missing) {
3230643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
324e8f14785SLisandro Dalcin                 else ++onz[key.i - rStart];
32563a3b9bcSJacob Faibussowitsch               } else SETERRQ(PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j);
32683c47955SMatthew G. Knepley             }
327fc7c92abSMatthew G. Knepley           }
328fc7c92abSMatthew G. Knepley         }
3299566063dSJacob Faibussowitsch         PetscCall(PetscFree(cindices));
33083c47955SMatthew G. Knepley       }
3319566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
33283c47955SMatthew G. Knepley     }
33383c47955SMatthew G. Knepley   }
3349566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
3359566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
3369566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
3379566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
3389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(maxC * totDim, &elemMat, maxC, &rowIDXs, maxC * dim, &xi));
33983c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
340ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
34183c47955SMatthew G. Knepley     PetscObject     obj;
342ef0bb6c7SMatthew G. Knepley     PetscReal      *coords;
3430643ed39SMatthew G. Knepley     PetscInt        Nc, i;
34483c47955SMatthew G. Knepley 
3459566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
3469566063dSJacob Faibussowitsch     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
34763a3b9bcSJacob Faibussowitsch     PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc);
3489566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
34983c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
35083c47955SMatthew G. Knepley       PetscInt *findices, *cindices;
35183c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
3520643ed39SMatthew G. Knepley       PetscInt  p, c;
35383c47955SMatthew G. Knepley 
3540643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
3559566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
3569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3579566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
358ad540459SPierre Jolivet       for (p = 0; p < numCIndices; ++p) CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &coords[cindices[p] * dim], &xi[p * dim]);
3599566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
36083c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
3619566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elemMat, numCIndices * totDim));
36283c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
3630643ed39SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
3640643ed39SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
3650643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
366ef0bb6c7SMatthew G. Knepley             elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
36783c47955SMatthew G. Knepley           }
3680643ed39SMatthew G. Knepley         }
3690643ed39SMatthew G. Knepley       }
370adb2528bSMark Adams       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
3719566063dSJacob Faibussowitsch       if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
3729566063dSJacob Faibussowitsch       PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES));
3739566063dSJacob Faibussowitsch       PetscCall(PetscFree(cindices));
3749566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3759566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
37683c47955SMatthew G. Knepley     }
3779566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
37883c47955SMatthew G. Knepley   }
3799566063dSJacob Faibussowitsch   PetscCall(PetscFree3(elemMat, rowIDXs, xi));
3809566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
3819566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
3829566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
3839566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
38483c47955SMatthew G. Knepley   PetscFunctionReturn(0);
38583c47955SMatthew G. Knepley }
38683c47955SMatthew G. Knepley 
387d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */
3889371c9d4SSatish Balay static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m) {
389d0c080abSJoseph Pusztay   Vec      field;
390d0c080abSJoseph Pusztay   PetscInt size;
391d0c080abSJoseph Pusztay 
392d0c080abSJoseph Pusztay   PetscFunctionBegin;
3939566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(sw, &field));
3949566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(field, &size));
3959566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(sw, &field));
3969566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, m));
3979566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*m));
3989566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size));
3999566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL));
4009566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(*m));
4019566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY));
4029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY));
4039566063dSJacob Faibussowitsch   PetscCall(MatShift(*m, 1.0));
4049566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*m, sw));
405d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
406d0c080abSJoseph Pusztay }
407d0c080abSJoseph Pusztay 
408adb2528bSMark Adams /* FEM cols, Particle rows */
4099371c9d4SSatish Balay static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass) {
410895a1698SMatthew G. Knepley   PetscSection gsf;
41183c47955SMatthew G. Knepley   PetscInt     m, n;
41283c47955SMatthew G. Knepley   void        *ctx;
41383c47955SMatthew G. Knepley 
41483c47955SMatthew G. Knepley   PetscFunctionBegin;
4159566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
4169566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
4179566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dmCoarse, &n));
4189566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
4199566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE));
4209566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
4219566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
42283c47955SMatthew G. Knepley 
4239566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
4249566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
42583c47955SMatthew G. Knepley   PetscFunctionReturn(0);
42683c47955SMatthew G. Knepley }
42783c47955SMatthew G. Knepley 
4289371c9d4SSatish Balay static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) {
4294cc7f7b2SMatthew G. Knepley   const char  *name = "Mass Matrix Square";
4304cc7f7b2SMatthew G. Knepley   MPI_Comm     comm;
4314cc7f7b2SMatthew G. Knepley   PetscDS      prob;
4324cc7f7b2SMatthew G. Knepley   PetscSection fsection, globalFSection;
4334cc7f7b2SMatthew G. Knepley   PetscHSetIJ  ht;
4344cc7f7b2SMatthew G. Knepley   PetscLayout  rLayout, colLayout;
4354cc7f7b2SMatthew G. Knepley   PetscInt    *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
4364cc7f7b2SMatthew G. Knepley   PetscInt     locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4374cc7f7b2SMatthew G. Knepley   PetscReal   *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
4384cc7f7b2SMatthew G. Knepley   PetscScalar *elemMat, *elemMatSq;
4394cc7f7b2SMatthew G. Knepley   PetscInt     cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
4404cc7f7b2SMatthew G. Knepley 
4414cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
4429566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
4439566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &cdim));
4449566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
4459566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
4469566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
4479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ));
4489566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
4499566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
4509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
4519566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
4524cc7f7b2SMatthew G. Knepley 
4539566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
4549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
4559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
4569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
4579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
4589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
4594cc7f7b2SMatthew G. Knepley 
4609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
4619566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
4629566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
4639566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
4649566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
4659566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
4664cc7f7b2SMatthew G. Knepley 
4679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmf, &depth));
4689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize));
4694cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth);
4709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxAdjSize, &adj));
4714cc7f7b2SMatthew G. Knepley 
4729566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
4739566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
4744cc7f7b2SMatthew G. Knepley   /* Count nonzeros
4754cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
4764cc7f7b2SMatthew G. Knepley   */
4779566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
4784cc7f7b2SMatthew G. Knepley   for (cell = cStart; cell < cEnd; ++cell) {
4794cc7f7b2SMatthew G. Knepley     PetscInt  i;
4804cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
4814cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
4824cc7f7b2SMatthew G. Knepley #if 0
4834cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
4844cc7f7b2SMatthew G. Knepley #endif
4854cc7f7b2SMatthew G. Knepley 
4869566063dSJacob Faibussowitsch     PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
4874cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
4884cc7f7b2SMatthew G. Knepley     /* Diagonal block */
489ad540459SPierre Jolivet     for (i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices;
4904cc7f7b2SMatthew G. Knepley #if 0
4914cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
4929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj));
4934cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
4944cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
4954cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
4964cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
4974cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
4984cc7f7b2SMatthew G. Knepley 
4999566063dSJacob Faibussowitsch         PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
5004cc7f7b2SMatthew G. Knepley         {
5014cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
5024cc7f7b2SMatthew G. Knepley           PetscBool      missing;
5034cc7f7b2SMatthew G. Knepley 
5044cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
5054cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
5064cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
5074cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
5084cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
5094cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
5109566063dSJacob Faibussowitsch               PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
5114cc7f7b2SMatthew G. Knepley               if (missing) {
5124cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
5134cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
5144cc7f7b2SMatthew G. Knepley               }
5154cc7f7b2SMatthew G. Knepley             }
5164cc7f7b2SMatthew G. Knepley           }
5174cc7f7b2SMatthew G. Knepley         }
5189566063dSJacob Faibussowitsch         PetscCall(PetscFree(ncindices));
5194cc7f7b2SMatthew G. Knepley       }
5204cc7f7b2SMatthew G. Knepley     }
5214cc7f7b2SMatthew G. Knepley #endif
5229566063dSJacob Faibussowitsch     PetscCall(PetscFree(cindices));
5234cc7f7b2SMatthew G. Knepley   }
5249566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
5259566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
5269566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
5279566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
5289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi));
5294cc7f7b2SMatthew G. Knepley   /* Fill in values
5304cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
5314cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
5324cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
5334cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
5344cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
5354cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
5364cc7f7b2SMatthew G. Knepley          Insert block
5374cc7f7b2SMatthew G. Knepley   */
5384cc7f7b2SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
5394cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
5404cc7f7b2SMatthew G. Knepley     PetscObject     obj;
5414cc7f7b2SMatthew G. Knepley     PetscReal      *coords;
5424cc7f7b2SMatthew G. Knepley     PetscInt        Nc, i;
5434cc7f7b2SMatthew G. Knepley 
5449566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5459566063dSJacob Faibussowitsch     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
54663a3b9bcSJacob Faibussowitsch     PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc);
5479566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
5484cc7f7b2SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
5494cc7f7b2SMatthew G. Knepley       PetscInt *findices, *cindices;
5504cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
5514cc7f7b2SMatthew G. Knepley       PetscInt  p, c;
5524cc7f7b2SMatthew G. Knepley 
5534cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5549566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
5559566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5569566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
557ad540459SPierre Jolivet       for (p = 0; p < numCIndices; ++p) CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p] * cdim], &xi[p * cdim]);
5589566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
5594cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
5609566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elemMat, numCIndices * totDim));
5614cc7f7b2SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
5624cc7f7b2SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
5634cc7f7b2SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
5644cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
5654cc7f7b2SMatthew G. Knepley             elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
5664cc7f7b2SMatthew G. Knepley           }
5674cc7f7b2SMatthew G. Knepley         }
5684cc7f7b2SMatthew G. Knepley       }
5699566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
5704cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
5719566063dSJacob Faibussowitsch       if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
5724cc7f7b2SMatthew G. Knepley       /* Block diagonal */
57378884ca7SMatthew G. Knepley       if (numCIndices) {
5744cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
5754cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
5764cc7f7b2SMatthew G. Knepley 
5779566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numCIndices, &blasn));
5789566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numFIndices, &blask));
579792fecdfSBarry Smith         PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn));
5804cc7f7b2SMatthew G. Knepley       }
5819566063dSJacob Faibussowitsch       PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES));
5824cc7f7b2SMatthew G. Knepley       /* TODO Off-diagonal */
5839566063dSJacob Faibussowitsch       PetscCall(PetscFree(cindices));
5849566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5854cc7f7b2SMatthew G. Knepley     }
5869566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
5874cc7f7b2SMatthew G. Knepley   }
5889566063dSJacob Faibussowitsch   PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi));
5899566063dSJacob Faibussowitsch   PetscCall(PetscFree(adj));
5909566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
5919566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
5929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
5939566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
5944cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
5954cc7f7b2SMatthew G. Knepley }
5964cc7f7b2SMatthew G. Knepley 
5974cc7f7b2SMatthew G. Knepley /*@C
5984cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
5994cc7f7b2SMatthew G. Knepley 
6004cc7f7b2SMatthew G. Knepley   Collective on dmCoarse
6014cc7f7b2SMatthew G. Knepley 
6024cc7f7b2SMatthew G. Knepley   Input parameters:
6034cc7f7b2SMatthew G. Knepley + dmCoarse - a DMSwarm
6044cc7f7b2SMatthew G. Knepley - dmFine   - a DMPlex
6054cc7f7b2SMatthew G. Knepley 
6064cc7f7b2SMatthew G. Knepley   Output parameter:
6074cc7f7b2SMatthew G. Knepley . mass     - the square of the particle mass matrix
6084cc7f7b2SMatthew G. Knepley 
6094cc7f7b2SMatthew G. Knepley   Level: advanced
6104cc7f7b2SMatthew G. Knepley 
6114cc7f7b2SMatthew G. Knepley   Notes:
6124cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
6134cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
6144cc7f7b2SMatthew G. Knepley 
615db781477SPatrick Sanan .seealso: `DMCreateMassMatrix()`
6164cc7f7b2SMatthew G. Knepley @*/
6179371c9d4SSatish Balay PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass) {
6184cc7f7b2SMatthew G. Knepley   PetscInt n;
6194cc7f7b2SMatthew G. Knepley   void    *ctx;
6204cc7f7b2SMatthew G. Knepley 
6214cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
6229566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dmCoarse, &n));
6239566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
6249566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE));
6259566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
6269566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
6274cc7f7b2SMatthew G. Knepley 
6289566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
6299566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view"));
6304cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6314cc7f7b2SMatthew G. Knepley }
6324cc7f7b2SMatthew G. Knepley 
633fb1bcc12SMatthew G. Knepley /*@C
634d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
635d3a51819SDave May 
636d083f849SBarry Smith    Collective on dm
637d3a51819SDave May 
638d3a51819SDave May    Input parameters:
63962741f57SDave May +  dm - a DMSwarm
64062741f57SDave May -  fieldname - the textual name given to a registered field
641d3a51819SDave May 
6428b8a3813SDave May    Output parameter:
643d3a51819SDave May .  vec - the vector
644d3a51819SDave May 
645d3a51819SDave May    Level: beginner
646d3a51819SDave May 
6478b8a3813SDave May    Notes:
6488b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
6498b8a3813SDave May 
650db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()`
651d3a51819SDave May @*/
6529371c9d4SSatish Balay PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) {
653fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
654b5bcf523SDave May 
655fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
6569566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
657b5bcf523SDave May   PetscFunctionReturn(0);
658b5bcf523SDave May }
659b5bcf523SDave May 
660d3a51819SDave May /*@C
661d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
662d3a51819SDave May 
663d083f849SBarry Smith    Collective on dm
664d3a51819SDave May 
665d3a51819SDave May    Input parameters:
66662741f57SDave May +  dm - a DMSwarm
66762741f57SDave May -  fieldname - the textual name given to a registered field
668d3a51819SDave May 
6698b8a3813SDave May    Output parameter:
670d3a51819SDave May .  vec - the vector
671d3a51819SDave May 
672d3a51819SDave May    Level: beginner
673d3a51819SDave May 
674db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
675d3a51819SDave May @*/
6769371c9d4SSatish Balay PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) {
677fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
6789566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
679b5bcf523SDave May   PetscFunctionReturn(0);
680b5bcf523SDave May }
681b5bcf523SDave May 
682fb1bcc12SMatthew G. Knepley /*@C
683fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
684fb1bcc12SMatthew G. Knepley 
685d083f849SBarry Smith    Collective on dm
686fb1bcc12SMatthew G. Knepley 
687fb1bcc12SMatthew G. Knepley    Input parameters:
68862741f57SDave May +  dm - a DMSwarm
68962741f57SDave May -  fieldname - the textual name given to a registered field
690fb1bcc12SMatthew G. Knepley 
6918b8a3813SDave May    Output parameter:
692fb1bcc12SMatthew G. Knepley .  vec - the vector
693fb1bcc12SMatthew G. Knepley 
694fb1bcc12SMatthew G. Knepley    Level: beginner
695fb1bcc12SMatthew G. Knepley 
6968b8a3813SDave May    Notes:
6978b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
6988b8a3813SDave May 
699db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
700fb1bcc12SMatthew G. Knepley @*/
7019371c9d4SSatish Balay PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) {
702fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
703bbe8250bSMatthew G. Knepley 
704fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
7059566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
706fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
707bbe8250bSMatthew G. Knepley }
708fb1bcc12SMatthew G. Knepley 
709fb1bcc12SMatthew G. Knepley /*@C
710fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
711fb1bcc12SMatthew G. Knepley 
712d083f849SBarry Smith    Collective on dm
713fb1bcc12SMatthew G. Knepley 
714fb1bcc12SMatthew G. Knepley    Input parameters:
71562741f57SDave May +  dm - a DMSwarm
71662741f57SDave May -  fieldname - the textual name given to a registered field
717fb1bcc12SMatthew G. Knepley 
7188b8a3813SDave May    Output parameter:
719fb1bcc12SMatthew G. Knepley .  vec - the vector
720fb1bcc12SMatthew G. Knepley 
721fb1bcc12SMatthew G. Knepley    Level: beginner
722fb1bcc12SMatthew G. Knepley 
723db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()`
724fb1bcc12SMatthew G. Knepley @*/
7259371c9d4SSatish Balay PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) {
726fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
7279566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
728bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
729bbe8250bSMatthew G. Knepley }
730bbe8250bSMatthew G. Knepley 
731d3a51819SDave May /*@C
732d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
733d3a51819SDave May 
734d083f849SBarry Smith    Collective on dm
735d3a51819SDave May 
736d3a51819SDave May    Input parameter:
737d3a51819SDave May .  dm - a DMSwarm
738d3a51819SDave May 
739d3a51819SDave May    Level: beginner
740d3a51819SDave May 
741d3a51819SDave May    Notes:
7428b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
743d3a51819SDave May 
744db781477SPatrick Sanan .seealso: `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
745db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
746d3a51819SDave May @*/
7479371c9d4SSatish Balay PetscErrorCode DMSwarmInitializeFieldRegister(DM dm) {
7485f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
7493454631fSDave May 
750521f74f9SMatthew G. Knepley   PetscFunctionBegin;
751cc651181SDave May   if (!swarm->field_registration_initialized) {
7525f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
7539566063dSJacob Faibussowitsch     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifer */
7549566063dSJacob Faibussowitsch     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT));  /* used for communication */
755cc651181SDave May   }
7565f50eb2eSDave May   PetscFunctionReturn(0);
7575f50eb2eSDave May }
7585f50eb2eSDave May 
75974d0cae8SMatthew G. Knepley /*@
760d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
761d3a51819SDave May 
762d083f849SBarry Smith    Collective on dm
763d3a51819SDave May 
764d3a51819SDave May    Input parameter:
765d3a51819SDave May .  dm - a DMSwarm
766d3a51819SDave May 
767d3a51819SDave May    Level: beginner
768d3a51819SDave May 
769d3a51819SDave May    Notes:
77062741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
771d3a51819SDave May 
772db781477SPatrick Sanan .seealso: `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
773db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
774d3a51819SDave May @*/
7759371c9d4SSatish Balay PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm) {
7765f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
7776845f8f5SDave May 
778521f74f9SMatthew G. Knepley   PetscFunctionBegin;
77948a46eb9SPierre Jolivet   if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db));
780f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
7815f50eb2eSDave May   PetscFunctionReturn(0);
7825f50eb2eSDave May }
7835f50eb2eSDave May 
78474d0cae8SMatthew G. Knepley /*@
785d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
786d3a51819SDave May 
787d3a51819SDave May    Not collective
788d3a51819SDave May 
789d3a51819SDave May    Input parameters:
79062741f57SDave May +  dm - a DMSwarm
791d3a51819SDave May .  nlocal - the length of each registered field
79262741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
793d3a51819SDave May 
794d3a51819SDave May    Level: beginner
795d3a51819SDave May 
796db781477SPatrick Sanan .seealso: `DMSwarmGetLocalSize()`
797d3a51819SDave May @*/
7989371c9d4SSatish Balay PetscErrorCode DMSwarmSetLocalSizes(DM dm, PetscInt nlocal, PetscInt buffer) {
7995f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
8005f50eb2eSDave May 
801521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0));
8039566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer));
8049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0));
8055f50eb2eSDave May   PetscFunctionReturn(0);
8065f50eb2eSDave May }
8075f50eb2eSDave May 
80874d0cae8SMatthew G. Knepley /*@
809d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
810d3a51819SDave May 
811d083f849SBarry Smith    Collective on dm
812d3a51819SDave May 
813d3a51819SDave May    Input parameters:
81462741f57SDave May +  dm - a DMSwarm
81562741f57SDave May -  dmcell - the DM to attach to the DMSwarm
816d3a51819SDave May 
817d3a51819SDave May    Level: beginner
818d3a51819SDave May 
819d3a51819SDave May    Notes:
820d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
8218b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
822d3a51819SDave May 
823db781477SPatrick Sanan .seealso: `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()`
824d3a51819SDave May @*/
8259371c9d4SSatish Balay PetscErrorCode DMSwarmSetCellDM(DM dm, DM dmcell) {
826b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
827521f74f9SMatthew G. Knepley 
828521f74f9SMatthew G. Knepley   PetscFunctionBegin;
829b16650c8SDave May   swarm->dmcell = dmcell;
830b16650c8SDave May   PetscFunctionReturn(0);
831b16650c8SDave May }
832b16650c8SDave May 
83374d0cae8SMatthew G. Knepley /*@
834d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
835d3a51819SDave May 
836d083f849SBarry Smith    Collective on dm
837d3a51819SDave May 
838d3a51819SDave May    Input parameter:
839d3a51819SDave May .  dm - a DMSwarm
840d3a51819SDave May 
841d3a51819SDave May    Output parameter:
842d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
843d3a51819SDave May 
844d3a51819SDave May    Level: beginner
845d3a51819SDave May 
846db781477SPatrick Sanan .seealso: `DMSwarmSetCellDM()`
847d3a51819SDave May @*/
8489371c9d4SSatish Balay PetscErrorCode DMSwarmGetCellDM(DM dm, DM *dmcell) {
849fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
850521f74f9SMatthew G. Knepley 
851521f74f9SMatthew G. Knepley   PetscFunctionBegin;
852fe39f135SDave May   *dmcell = swarm->dmcell;
853fe39f135SDave May   PetscFunctionReturn(0);
854fe39f135SDave May }
855fe39f135SDave May 
85674d0cae8SMatthew G. Knepley /*@
857d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
858d3a51819SDave May 
859d3a51819SDave May    Not collective
860d3a51819SDave May 
861d3a51819SDave May    Input parameter:
862d3a51819SDave May .  dm - a DMSwarm
863d3a51819SDave May 
864d3a51819SDave May    Output parameter:
865d3a51819SDave May .  nlocal - the length of each registered field
866d3a51819SDave May 
867d3a51819SDave May    Level: beginner
868d3a51819SDave May 
869db781477SPatrick Sanan .seealso: `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()`
870d3a51819SDave May @*/
8719371c9d4SSatish Balay PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal) {
872dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
873dcf43ee8SDave May 
874521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8759566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL));
876dcf43ee8SDave May   PetscFunctionReturn(0);
877dcf43ee8SDave May }
878dcf43ee8SDave May 
87974d0cae8SMatthew G. Knepley /*@
880d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
881d3a51819SDave May 
882d083f849SBarry Smith    Collective on dm
883d3a51819SDave May 
884d3a51819SDave May    Input parameter:
885d3a51819SDave May .  dm - a DMSwarm
886d3a51819SDave May 
887d3a51819SDave May    Output parameter:
888d3a51819SDave May .  n - the total length of each registered field
889d3a51819SDave May 
890d3a51819SDave May    Level: beginner
891d3a51819SDave May 
892d3a51819SDave May    Note:
893d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
894d3a51819SDave May 
895db781477SPatrick Sanan .seealso: `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()`
896d3a51819SDave May @*/
8979371c9d4SSatish Balay PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n) {
898dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
8995627991aSBarry Smith   PetscInt  nlocal;
900dcf43ee8SDave May 
901521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9029566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
9039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
904dcf43ee8SDave May   PetscFunctionReturn(0);
905dcf43ee8SDave May }
906dcf43ee8SDave May 
907d3a51819SDave May /*@C
9088b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
909d3a51819SDave May 
910d083f849SBarry Smith    Collective on dm
911d3a51819SDave May 
912d3a51819SDave May    Input parameters:
91362741f57SDave May +  dm - a DMSwarm
914d3a51819SDave May .  fieldname - the textual name to identify this field
915d3a51819SDave May .  blocksize - the number of each data type
91662741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
917d3a51819SDave May 
918d3a51819SDave May    Level: beginner
919d3a51819SDave May 
920d3a51819SDave May    Notes:
9218b8a3813SDave May    The textual name for each registered field must be unique.
922d3a51819SDave May 
923db781477SPatrick Sanan .seealso: `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
924d3a51819SDave May @*/
9259371c9d4SSatish Balay PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type) {
926b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
927b62e03f8SDave May   size_t    size;
928b62e03f8SDave May 
929521f74f9SMatthew G. Knepley   PetscFunctionBegin;
93028b400f6SJacob Faibussowitsch   PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first");
93128b400f6SJacob Faibussowitsch   PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
9325f50eb2eSDave May 
93308401ef6SPierre Jolivet   PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
93408401ef6SPierre Jolivet   PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
93508401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
93608401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
93708401ef6SPierre Jolivet   PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
938b62e03f8SDave May 
9399566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &size));
940b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
9419566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL));
94252c3ed93SDave May   {
94377048351SPatrick Sanan     DMSwarmDataField gfield;
94452c3ed93SDave May 
9459566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
9469566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
94752c3ed93SDave May   }
948b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = type;
949b62e03f8SDave May   PetscFunctionReturn(0);
950b62e03f8SDave May }
951b62e03f8SDave May 
952d3a51819SDave May /*@C
953d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
954d3a51819SDave May 
955d083f849SBarry Smith    Collective on dm
956d3a51819SDave May 
957d3a51819SDave May    Input parameters:
95862741f57SDave May +  dm - a DMSwarm
959d3a51819SDave May .  fieldname - the textual name to identify this field
96062741f57SDave May -  size - the size in bytes of the user struct of each data type
961d3a51819SDave May 
962d3a51819SDave May    Level: beginner
963d3a51819SDave May 
964d3a51819SDave May    Notes:
9658b8a3813SDave May    The textual name for each registered field must be unique.
966d3a51819SDave May 
967db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()`
968d3a51819SDave May @*/
9699371c9d4SSatish Balay PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size) {
970b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
971b62e03f8SDave May 
972521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9739566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL));
974b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT;
975b62e03f8SDave May   PetscFunctionReturn(0);
976b62e03f8SDave May }
977b62e03f8SDave May 
978d3a51819SDave May /*@C
979d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
980d3a51819SDave May 
981d083f849SBarry Smith    Collective on dm
982d3a51819SDave May 
983d3a51819SDave May    Input parameters:
98462741f57SDave May +  dm - a DMSwarm
985d3a51819SDave May .  fieldname - the textual name to identify this field
986d3a51819SDave May .  size - the size in bytes of the user data type
98762741f57SDave May -  blocksize - the number of each data type
988d3a51819SDave May 
989d3a51819SDave May    Level: beginner
990d3a51819SDave May 
991d3a51819SDave May    Notes:
9928b8a3813SDave May    The textual name for each registered field must be unique.
993d3a51819SDave May 
994db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
995d3a51819SDave May @*/
9969371c9d4SSatish Balay PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize) {
997b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
998b62e03f8SDave May 
999521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10009566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL));
1001320740a0SDave May   {
100277048351SPatrick Sanan     DMSwarmDataField gfield;
1003320740a0SDave May 
10049566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
10059566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
1006320740a0SDave May   }
1007b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
1008b62e03f8SDave May   PetscFunctionReturn(0);
1009b62e03f8SDave May }
1010b62e03f8SDave May 
1011d3a51819SDave May /*@C
1012d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1013d3a51819SDave May 
1014d3a51819SDave May    Not collective
1015d3a51819SDave May 
1016d3a51819SDave May    Input parameters:
101762741f57SDave May +  dm - a DMSwarm
101862741f57SDave May -  fieldname - the textual name to identify this field
1019d3a51819SDave May 
1020d3a51819SDave May    Output parameters:
102162741f57SDave May +  blocksize - the number of each data type
1022d3a51819SDave May .  type - the data type
102362741f57SDave May -  data - pointer to raw array
1024d3a51819SDave May 
1025d3a51819SDave May    Level: beginner
1026d3a51819SDave May 
1027d3a51819SDave May    Notes:
10288b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
1029d3a51819SDave May 
1030db781477SPatrick Sanan .seealso: `DMSwarmRestoreField()`
1031d3a51819SDave May @*/
10329371c9d4SSatish Balay PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) {
1033b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
103477048351SPatrick Sanan   DMSwarmDataField gfield;
1035b62e03f8SDave May 
1036521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10379566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
10389566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
10399566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetAccess(gfield));
10409566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetEntries(gfield, data));
1041ad540459SPierre Jolivet   if (blocksize) *blocksize = gfield->bs;
1042ad540459SPierre Jolivet   if (type) *type = gfield->petsc_type;
1043b62e03f8SDave May   PetscFunctionReturn(0);
1044b62e03f8SDave May }
1045b62e03f8SDave May 
1046d3a51819SDave May /*@C
1047d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1048d3a51819SDave May 
1049d3a51819SDave May    Not collective
1050d3a51819SDave May 
1051d3a51819SDave May    Input parameters:
105262741f57SDave May +  dm - a DMSwarm
105362741f57SDave May -  fieldname - the textual name to identify this field
1054d3a51819SDave May 
1055d3a51819SDave May    Output parameters:
105662741f57SDave May +  blocksize - the number of each data type
1057d3a51819SDave May .  type - the data type
105862741f57SDave May -  data - pointer to raw array
1059d3a51819SDave May 
1060d3a51819SDave May    Level: beginner
1061d3a51819SDave May 
1062d3a51819SDave May    Notes:
10638b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
1064d3a51819SDave May 
1065db781477SPatrick Sanan .seealso: `DMSwarmGetField()`
1066d3a51819SDave May @*/
10679371c9d4SSatish Balay PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) {
1068b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
106977048351SPatrick Sanan   DMSwarmDataField gfield;
1070b62e03f8SDave May 
1071521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10729566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
10739566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
1074b62e03f8SDave May   if (data) *data = NULL;
1075b62e03f8SDave May   PetscFunctionReturn(0);
1076b62e03f8SDave May }
1077b62e03f8SDave May 
107874d0cae8SMatthew G. Knepley /*@
1079d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
1080d3a51819SDave May 
1081d3a51819SDave May    Not collective
1082d3a51819SDave May 
1083d3a51819SDave May    Input parameter:
1084d3a51819SDave May .  dm - a DMSwarm
1085d3a51819SDave May 
1086d3a51819SDave May    Level: beginner
1087d3a51819SDave May 
1088d3a51819SDave May    Notes:
10898b8a3813SDave May    The new point will have all fields initialized to zero.
1090d3a51819SDave May 
1091db781477SPatrick Sanan .seealso: `DMSwarmAddNPoints()`
1092d3a51819SDave May @*/
10939371c9d4SSatish Balay PetscErrorCode DMSwarmAddPoint(DM dm) {
1094cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1095cb1d1399SDave May 
1096521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10979566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
10989566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
10999566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketAddPoint(swarm->db));
11009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
1101cb1d1399SDave May   PetscFunctionReturn(0);
1102cb1d1399SDave May }
1103cb1d1399SDave May 
110474d0cae8SMatthew G. Knepley /*@
1105d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
1106d3a51819SDave May 
1107d3a51819SDave May    Not collective
1108d3a51819SDave May 
1109d3a51819SDave May    Input parameters:
111062741f57SDave May +  dm - a DMSwarm
111162741f57SDave May -  npoints - the number of new points to add
1112d3a51819SDave May 
1113d3a51819SDave May    Level: beginner
1114d3a51819SDave May 
1115d3a51819SDave May    Notes:
11168b8a3813SDave May    The new point will have all fields initialized to zero.
1117d3a51819SDave May 
1118db781477SPatrick Sanan .seealso: `DMSwarmAddPoint()`
1119d3a51819SDave May @*/
11209371c9d4SSatish Balay PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints) {
1121cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1122cb1d1399SDave May   PetscInt  nlocal;
1123cb1d1399SDave May 
1124521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
11269566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1127cb1d1399SDave May   nlocal = nlocal + npoints;
11289566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
11299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
1130cb1d1399SDave May   PetscFunctionReturn(0);
1131cb1d1399SDave May }
1132cb1d1399SDave May 
113374d0cae8SMatthew G. Knepley /*@
1134d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
1135d3a51819SDave May 
1136d3a51819SDave May    Not collective
1137d3a51819SDave May 
1138d3a51819SDave May    Input parameter:
1139d3a51819SDave May .  dm - a DMSwarm
1140d3a51819SDave May 
1141d3a51819SDave May    Level: beginner
1142d3a51819SDave May 
1143db781477SPatrick Sanan .seealso: `DMSwarmRemovePointAtIndex()`
1144d3a51819SDave May @*/
11459371c9d4SSatish Balay PetscErrorCode DMSwarmRemovePoint(DM dm) {
1146cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1147cb1d1399SDave May 
1148521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
11509566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePoint(swarm->db));
11519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
1152cb1d1399SDave May   PetscFunctionReturn(0);
1153cb1d1399SDave May }
1154cb1d1399SDave May 
115574d0cae8SMatthew G. Knepley /*@
1156d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
1157d3a51819SDave May 
1158d3a51819SDave May    Not collective
1159d3a51819SDave May 
1160d3a51819SDave May    Input parameters:
116162741f57SDave May +  dm - a DMSwarm
116262741f57SDave May -  idx - index of point to remove
1163d3a51819SDave May 
1164d3a51819SDave May    Level: beginner
1165d3a51819SDave May 
1166db781477SPatrick Sanan .seealso: `DMSwarmRemovePoint()`
1167d3a51819SDave May @*/
11689371c9d4SSatish Balay PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx) {
1169cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1170cb1d1399SDave May 
1171521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
11739566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx));
11749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
1175cb1d1399SDave May   PetscFunctionReturn(0);
1176cb1d1399SDave May }
1177b62e03f8SDave May 
117874d0cae8SMatthew G. Knepley /*@
1179ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
1180ba4fc9c6SDave May 
1181ba4fc9c6SDave May    Not collective
1182ba4fc9c6SDave May 
1183ba4fc9c6SDave May    Input parameters:
1184ba4fc9c6SDave May +  dm - a DMSwarm
1185ba4fc9c6SDave May .  pi - the index of the point to copy
1186ba4fc9c6SDave May -  pj - the point index where the copy should be located
1187ba4fc9c6SDave May 
1188ba4fc9c6SDave May  Level: beginner
1189ba4fc9c6SDave May 
1190db781477SPatrick Sanan .seealso: `DMSwarmRemovePoint()`
1191ba4fc9c6SDave May @*/
11929371c9d4SSatish Balay PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj) {
1193ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1194ba4fc9c6SDave May 
1195ba4fc9c6SDave May   PetscFunctionBegin;
11969566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
11979566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj));
1198ba4fc9c6SDave May   PetscFunctionReturn(0);
1199ba4fc9c6SDave May }
1200ba4fc9c6SDave May 
12019371c9d4SSatish Balay PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points) {
1202521f74f9SMatthew G. Knepley   PetscFunctionBegin;
12039566063dSJacob Faibussowitsch   PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points));
12043454631fSDave May   PetscFunctionReturn(0);
12053454631fSDave May }
12063454631fSDave May 
120774d0cae8SMatthew G. Knepley /*@
1208d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
1209d3a51819SDave May 
1210d083f849SBarry Smith    Collective on dm
1211d3a51819SDave May 
1212d3a51819SDave May    Input parameters:
121362741f57SDave May +  dm - the DMSwarm
121462741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1215d3a51819SDave May 
1216d3a51819SDave May    Notes:
1217a5b23f4aSJose E. Roman    The DM will be modified to accommodate received points.
12188b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
12198b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
1220d3a51819SDave May 
1221d3a51819SDave May    Level: advanced
1222d3a51819SDave May 
1223db781477SPatrick Sanan .seealso: `DMSwarmSetMigrateType()`
1224d3a51819SDave May @*/
12259371c9d4SSatish Balay PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points) {
1226f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1227f0cdbbbaSDave May 
1228521f74f9SMatthew G. Knepley   PetscFunctionBegin;
12299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0));
1230f0cdbbbaSDave May   switch (swarm->migrate_type) {
12319371c9d4SSatish Balay   case DMSWARM_MIGRATE_BASIC: PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points)); break;
12329371c9d4SSatish Balay   case DMSWARM_MIGRATE_DMCELLNSCATTER: PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points)); break;
12339371c9d4SSatish Balay   case DMSWARM_MIGRATE_DMCELLEXACT: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented");
12349371c9d4SSatish Balay   case DMSWARM_MIGRATE_USER: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented");
12359371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown");
1236f0cdbbbaSDave May   }
12379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0));
12389566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(dm));
12393454631fSDave May   PetscFunctionReturn(0);
12403454631fSDave May }
12413454631fSDave May 
1242f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize);
1243f0cdbbbaSDave May 
1244d3a51819SDave May /*
1245d3a51819SDave May  DMSwarmCollectViewCreate
1246d3a51819SDave May 
1247d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1248d3a51819SDave May 
1249d3a51819SDave May  Notes:
12508b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1251d3a51819SDave May  they have finished computations associated with the collected points
1252d3a51819SDave May */
1253d3a51819SDave May 
125474d0cae8SMatthew G. Knepley /*@
1255d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
12565627991aSBarry Smith                               in neighbour ranks into the DMSwarm
1257d3a51819SDave May 
1258d083f849SBarry Smith    Collective on dm
1259d3a51819SDave May 
1260d3a51819SDave May    Input parameter:
1261d3a51819SDave May .  dm - the DMSwarm
1262d3a51819SDave May 
1263d3a51819SDave May    Notes:
1264d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1265d3a51819SDave May    they have finished computations associated with the collected points
12668b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1267d3a51819SDave May 
1268d3a51819SDave May    Level: advanced
1269d3a51819SDave May 
1270db781477SPatrick Sanan .seealso: `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()`
1271d3a51819SDave May @*/
12729371c9d4SSatish Balay PetscErrorCode DMSwarmCollectViewCreate(DM dm) {
12732712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
12742712d1f2SDave May   PetscInt  ng;
12752712d1f2SDave May 
1276521f74f9SMatthew G. Knepley   PetscFunctionBegin;
127728b400f6SJacob Faibussowitsch   PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active");
12789566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &ng));
1279480eef7bSDave May   switch (swarm->collect_type) {
12809371c9d4SSatish Balay   case DMSWARM_COLLECT_BASIC: PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng)); break;
12819371c9d4SSatish Balay   case DMSWARM_COLLECT_DMDABOUNDINGBOX: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
12829371c9d4SSatish Balay   case DMSWARM_COLLECT_GENERAL: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented");
12839371c9d4SSatish Balay   default: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown");
1284480eef7bSDave May   }
1285480eef7bSDave May   swarm->collect_view_active       = PETSC_TRUE;
1286480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
12872712d1f2SDave May   PetscFunctionReturn(0);
12882712d1f2SDave May }
12892712d1f2SDave May 
129074d0cae8SMatthew G. Knepley /*@
1291d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1292d3a51819SDave May 
1293d083f849SBarry Smith    Collective on dm
1294d3a51819SDave May 
1295d3a51819SDave May    Input parameters:
1296d3a51819SDave May .  dm - the DMSwarm
1297d3a51819SDave May 
1298d3a51819SDave May    Notes:
1299d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1300d3a51819SDave May 
1301d3a51819SDave May    Level: advanced
1302d3a51819SDave May 
1303db781477SPatrick Sanan .seealso: `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()`
1304d3a51819SDave May @*/
13059371c9d4SSatish Balay PetscErrorCode DMSwarmCollectViewDestroy(DM dm) {
13062712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
13072712d1f2SDave May 
1308521f74f9SMatthew G. Knepley   PetscFunctionBegin;
130928b400f6SJacob Faibussowitsch   PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active");
13109566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1));
1311480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
13122712d1f2SDave May   PetscFunctionReturn(0);
13132712d1f2SDave May }
13143454631fSDave May 
13159371c9d4SSatish Balay PetscErrorCode DMSwarmSetUpPIC(DM dm) {
1316f0cdbbbaSDave May   PetscInt dim;
1317f0cdbbbaSDave May 
1318521f74f9SMatthew G. Knepley   PetscFunctionBegin;
13199566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetNumSpecies(dm, 1));
13209566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
132163a3b9bcSJacob Faibussowitsch   PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
132263a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
13239566063dSJacob Faibussowitsch   PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_coor, dim, PETSC_DOUBLE));
13249566063dSJacob Faibussowitsch   PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_cellid, 1, PETSC_INT));
1325f0cdbbbaSDave May   PetscFunctionReturn(0);
1326f0cdbbbaSDave May }
1327f0cdbbbaSDave May 
132874d0cae8SMatthew G. Knepley /*@
132931403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
133031403186SMatthew G. Knepley 
133131403186SMatthew G. Knepley   Collective on dm
133231403186SMatthew G. Knepley 
133331403186SMatthew G. Knepley   Input parameters:
133431403186SMatthew G. Knepley + dm  - the DMSwarm
133531403186SMatthew G. Knepley - Npc - The number of particles per cell in the cell DM
133631403186SMatthew G. Knepley 
133731403186SMatthew G. Knepley   Notes:
133831403186SMatthew G. Knepley   The user must use DMSwarmSetCellDM() to set the cell DM first. The particles are placed randomly inside each cell. If only
133931403186SMatthew G. Knepley   one particle is in each cell, it is placed at the centroid.
134031403186SMatthew G. Knepley 
134131403186SMatthew G. Knepley   Level: intermediate
134231403186SMatthew G. Knepley 
1343db781477SPatrick Sanan .seealso: `DMSwarmSetCellDM()`
134431403186SMatthew G. Knepley @*/
13459371c9d4SSatish Balay PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc) {
134631403186SMatthew G. Knepley   DM             cdm;
134731403186SMatthew G. Knepley   PetscRandom    rnd;
134831403186SMatthew G. Knepley   DMPolytopeType ct;
134931403186SMatthew G. Knepley   PetscBool      simplex;
135031403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
135131403186SMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p;
135231403186SMatthew G. Knepley 
135331403186SMatthew G. Knepley   PetscFunctionBeginUser;
13549566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd));
13559566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0));
13569566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetType(rnd, PETSCRAND48));
135731403186SMatthew G. Knepley 
13589566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
13599566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(cdm, &dim));
13609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd));
13619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(cdm, cStart, &ct));
136231403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
136331403186SMatthew G. Knepley 
13649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ));
136531403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
13669566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
136731403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
136831403186SMatthew G. Knepley     if (Npc == 1) {
13699566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL));
137031403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d];
137131403186SMatthew G. Knepley     } else {
13729566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */
137331403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
137431403186SMatthew G. Knepley         const PetscInt n   = c * Npc + p;
137531403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
137631403186SMatthew G. Knepley 
137731403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
13789566063dSJacob Faibussowitsch           PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d]));
137931403186SMatthew G. Knepley           sum += refcoords[d];
138031403186SMatthew G. Knepley         }
13819371c9d4SSatish Balay         if (simplex && sum > 0.0)
13829371c9d4SSatish Balay           for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum;
138331403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]);
138431403186SMatthew G. Knepley       }
138531403186SMatthew G. Knepley     }
138631403186SMatthew G. Knepley   }
13879566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
13889566063dSJacob Faibussowitsch   PetscCall(PetscFree5(centroid, xi0, v0, J, invJ));
13899566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rnd));
139031403186SMatthew G. Knepley   PetscFunctionReturn(0);
139131403186SMatthew G. Knepley }
139231403186SMatthew G. Knepley 
139331403186SMatthew G. Knepley /*@
1394d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1395d3a51819SDave May 
1396d083f849SBarry Smith    Collective on dm
1397d3a51819SDave May 
1398d3a51819SDave May    Input parameters:
139962741f57SDave May +  dm - the DMSwarm
140062741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1401d3a51819SDave May 
1402d3a51819SDave May    Level: advanced
1403d3a51819SDave May 
1404db781477SPatrick Sanan .seealso: `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC`
1405d3a51819SDave May @*/
14069371c9d4SSatish Balay PetscErrorCode DMSwarmSetType(DM dm, DMSwarmType stype) {
1407f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1408f0cdbbbaSDave May 
1409521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1410f0cdbbbaSDave May   swarm->swarm_type = stype;
141148a46eb9SPierre Jolivet   if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(dm));
1412f0cdbbbaSDave May   PetscFunctionReturn(0);
1413f0cdbbbaSDave May }
1414f0cdbbbaSDave May 
14159371c9d4SSatish Balay PetscErrorCode DMSetup_Swarm(DM dm) {
14163454631fSDave May   DM_Swarm   *swarm = (DM_Swarm *)dm->data;
14173454631fSDave May   PetscMPIInt rank;
14183454631fSDave May   PetscInt    p, npoints, *rankval;
14193454631fSDave May 
1420521f74f9SMatthew G. Knepley   PetscFunctionBegin;
14213454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
14223454631fSDave May   swarm->issetup = PETSC_TRUE;
14233454631fSDave May 
1424f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1425f0cdbbbaSDave May     /* check dmcell exists */
142628b400f6SJacob Faibussowitsch     PetscCheck(swarm->dmcell, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires you call DMSwarmSetCellDM");
1427f0cdbbbaSDave May 
1428f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1429f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
14309566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n"));
1431f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1432f0cdbbbaSDave May     } else {
1433f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1434f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
14359566063dSJacob Faibussowitsch         PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n"));
1436f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1437f0cdbbbaSDave May 
1438f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
14399566063dSJacob Faibussowitsch         PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n"));
1440f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1441f0cdbbbaSDave May 
1442f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1443f0cdbbbaSDave May     }
1444f0cdbbbaSDave May   }
1445f0cdbbbaSDave May 
14469566063dSJacob Faibussowitsch   PetscCall(DMSwarmFinalizeFieldRegister(dm));
1447f0cdbbbaSDave May 
14483454631fSDave May   /* check some fields were registered */
144908401ef6SPierre Jolivet   PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()");
14503454631fSDave May 
14513454631fSDave May   /* check local sizes were set */
145208401ef6SPierre Jolivet   PetscCheck(swarm->db->L != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Local sizes must be set via DMSwarmSetLocalSizes()");
14533454631fSDave May 
14543454631fSDave May   /* initialize values in pid and rank placeholders */
14553454631fSDave May   /* TODO: [pid - use MPI_Scan] */
14569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
14579566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
14589566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
1459ad540459SPierre Jolivet   for (p = 0; p < npoints; p++) rankval[p] = (PetscInt)rank;
14609566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
14613454631fSDave May   PetscFunctionReturn(0);
14623454631fSDave May }
14633454631fSDave May 
1464dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1465dc5f5ce9SDave May 
14669371c9d4SSatish Balay PetscErrorCode DMDestroy_Swarm(DM dm) {
146757795646SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
146857795646SDave May 
146957795646SDave May   PetscFunctionBegin;
1470d0c080abSJoseph Pusztay   if (--swarm->refct > 0) PetscFunctionReturn(0);
14719566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&swarm->db));
147248a46eb9SPierre Jolivet   if (swarm->sort_context) PetscCall(DMSwarmSortDestroy(&swarm->sort_context));
14739566063dSJacob Faibussowitsch   PetscCall(PetscFree(swarm));
147457795646SDave May   PetscFunctionReturn(0);
147557795646SDave May }
147657795646SDave May 
14779371c9d4SSatish Balay PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer) {
1478a9ee3421SMatthew G. Knepley   DM         cdm;
1479a9ee3421SMatthew G. Knepley   PetscDraw  draw;
148031403186SMatthew G. Knepley   PetscReal *coords, oldPause, radius = 0.01;
1481a9ee3421SMatthew G. Knepley   PetscInt   Np, p, bs;
1482a9ee3421SMatthew G. Knepley 
1483a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
14849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL));
14859566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
14869566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
14879566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetPause(draw, &oldPause));
14889566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, 0.0));
14899566063dSJacob Faibussowitsch   PetscCall(DMView(cdm, viewer));
14909566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, oldPause));
1491a9ee3421SMatthew G. Knepley 
14929566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &Np));
14939566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **)&coords));
1494a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1495a9ee3421SMatthew G. Knepley     const PetscInt i = p * bs;
1496a9ee3421SMatthew G. Knepley 
14979566063dSJacob Faibussowitsch     PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE));
1498a9ee3421SMatthew G. Knepley   }
14999566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **)&coords));
15009566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
15019566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
15029566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1503a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1504a9ee3421SMatthew G. Knepley }
1505a9ee3421SMatthew G. Knepley 
15069371c9d4SSatish Balay static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer) {
15076a5217c0SMatthew G. Knepley   PetscViewerFormat format;
15086a5217c0SMatthew G. Knepley   PetscInt         *sizes;
15096a5217c0SMatthew G. Knepley   PetscInt          dim, Np, maxSize = 17;
15106a5217c0SMatthew G. Knepley   MPI_Comm          comm;
15116a5217c0SMatthew G. Knepley   PetscMPIInt       rank, size, p;
15126a5217c0SMatthew G. Knepley   const char       *name;
15136a5217c0SMatthew G. Knepley 
15146a5217c0SMatthew G. Knepley   PetscFunctionBegin;
15156a5217c0SMatthew G. Knepley   PetscCall(PetscViewerGetFormat(viewer, &format));
15166a5217c0SMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
15176a5217c0SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dm, &Np));
15186a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15196a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
15206a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
15216a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
152263a3b9bcSJacob Faibussowitsch   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
152363a3b9bcSJacob Faibussowitsch   else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
15246a5217c0SMatthew G. Knepley   if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes));
15256a5217c0SMatthew G. Knepley   else PetscCall(PetscCalloc1(3, &sizes));
15266a5217c0SMatthew G. Knepley   if (size < maxSize) {
15276a5217c0SMatthew G. Knepley     PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
15286a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of particles per rank:"));
15296a5217c0SMatthew G. Knepley     for (p = 0; p < size; ++p) {
15306a5217c0SMatthew G. Knepley       if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]));
15316a5217c0SMatthew G. Knepley     }
15326a5217c0SMatthew G. Knepley   } else {
15336a5217c0SMatthew G. Knepley     PetscInt locMinMax[2] = {Np, Np};
15346a5217c0SMatthew G. Knepley 
15356a5217c0SMatthew G. Knepley     PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
15366a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
15376a5217c0SMatthew G. Knepley   }
15386a5217c0SMatthew G. Knepley   PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
15396a5217c0SMatthew G. Knepley   PetscCall(PetscFree(sizes));
15406a5217c0SMatthew G. Knepley   if (format == PETSC_VIEWER_ASCII_INFO) {
15416a5217c0SMatthew G. Knepley     PetscInt *cell;
15426a5217c0SMatthew G. Knepley 
15436a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells containing each particle:\n"));
15446a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
15456a5217c0SMatthew G. Knepley     PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell));
154663a3b9bcSJacob Faibussowitsch     for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  p%d: %" PetscInt_FMT "\n", p, cell[p]));
15476a5217c0SMatthew G. Knepley     PetscCall(PetscViewerFlush(viewer));
15486a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
15496a5217c0SMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell));
15506a5217c0SMatthew G. Knepley   }
15516a5217c0SMatthew G. Knepley   PetscFunctionReturn(0);
15526a5217c0SMatthew G. Knepley }
15536a5217c0SMatthew G. Knepley 
15549371c9d4SSatish Balay PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer) {
15555f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
15565627991aSBarry Smith   PetscBool iascii, ibinary, isvtk, isdraw;
15575627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
15585627991aSBarry Smith   PetscBool ishdf5;
15595627991aSBarry Smith #endif
15605f50eb2eSDave May 
15615f50eb2eSDave May   PetscFunctionBegin;
15625f50eb2eSDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
15635f50eb2eSDave May   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
15649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
15659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
15669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
15675627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
15689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
15695627991aSBarry Smith #endif
15709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
15715f50eb2eSDave May   if (iascii) {
15726a5217c0SMatthew G. Knepley     PetscViewerFormat format;
15736a5217c0SMatthew G. Knepley 
15746a5217c0SMatthew G. Knepley     PetscCall(PetscViewerGetFormat(viewer, &format));
15756a5217c0SMatthew G. Knepley     switch (format) {
15769371c9d4SSatish Balay     case PETSC_VIEWER_ASCII_INFO_DETAIL: PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT)); break;
15776a5217c0SMatthew G. Knepley     default: PetscCall(DMView_Swarm_Ascii(dm, viewer));
15786a5217c0SMatthew G. Knepley     }
1579f7d195e4SLawrence Mitchell   } else {
15805f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
158148a46eb9SPierre Jolivet     if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer));
15825f50eb2eSDave May #endif
158348a46eb9SPierre Jolivet     if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer));
1584f7d195e4SLawrence Mitchell   }
15855f50eb2eSDave May   PetscFunctionReturn(0);
15865f50eb2eSDave May }
15875f50eb2eSDave May 
1588d0c080abSJoseph Pusztay /*@C
1589d0c080abSJoseph Pusztay    DMSwarmGetCellSwarm - Extracts a single cell from the DMSwarm object, returns it as a single cell DMSwarm.
1590d0c080abSJoseph Pusztay    The cell DM is filtered for fields of that cell, and the filtered DM is used as the cell DM of the new swarm object.
1591d0c080abSJoseph Pusztay 
1592d0c080abSJoseph Pusztay    Important: Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
1593d0c080abSJoseph Pusztay 
1594d0c080abSJoseph Pusztay    Noncollective
1595d0c080abSJoseph Pusztay 
1596d0c080abSJoseph Pusztay    Input parameters:
1597d0c080abSJoseph Pusztay +  sw - the DMSwarm
15985627991aSBarry Smith .  cellID - the integer id of the cell to be extracted and filtered
15995627991aSBarry Smith -  cellswarm - The DMSwarm to receive the cell
1600d0c080abSJoseph Pusztay 
1601d0c080abSJoseph Pusztay    Level: beginner
1602d0c080abSJoseph Pusztay 
16035627991aSBarry Smith    Notes:
16045627991aSBarry Smith       This presently only supports DMSWARM_PIC type
16055627991aSBarry Smith 
16065627991aSBarry Smith       Should be restored with DMSwarmRestoreCellSwarm()
1607d0c080abSJoseph Pusztay 
1608db781477SPatrick Sanan .seealso: `DMSwarmRestoreCellSwarm()`
1609d0c080abSJoseph Pusztay @*/
16109371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm) {
1611d0c080abSJoseph Pusztay   DM_Swarm *original = (DM_Swarm *)sw->data;
1612d0c080abSJoseph Pusztay   DMLabel   label;
1613d0c080abSJoseph Pusztay   DM        dmc, subdmc;
1614d0c080abSJoseph Pusztay   PetscInt *pids, particles, dim;
1615d0c080abSJoseph Pusztay 
1616d0c080abSJoseph Pusztay   PetscFunctionBegin;
1617d0c080abSJoseph Pusztay   /* Configure new swarm */
16189566063dSJacob Faibussowitsch   PetscCall(DMSetType(cellswarm, DMSWARM));
16199566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(sw, &dim));
16209566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(cellswarm, dim));
16219566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC));
1622d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
16239566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db));
16249566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
16259566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles));
16269566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
16279566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db));
16289566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
16299566063dSJacob Faibussowitsch   PetscCall(PetscFree(pids));
16309566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(sw, &dmc));
16319566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label));
16329566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(dmc, label));
16339566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cellID, 1));
16349566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dmc, label, 1, &subdmc));
16359566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetCellDM(cellswarm, subdmc));
16369566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
1637d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1638d0c080abSJoseph Pusztay }
1639d0c080abSJoseph Pusztay 
1640d0c080abSJoseph Pusztay /*@C
16415627991aSBarry Smith    DMSwarmRestoreCellSwarm - Restores a DMSwarm object obtained with DMSwarmGetCellSwarm(). All fields are copied back into the parent swarm.
1642d0c080abSJoseph Pusztay 
1643d0c080abSJoseph Pusztay    Noncollective
1644d0c080abSJoseph Pusztay 
1645d0c080abSJoseph Pusztay    Input parameters:
1646d0c080abSJoseph Pusztay +  sw - the parent DMSwarm
1647d0c080abSJoseph Pusztay .  cellID - the integer id of the cell to be copied back into the parent swarm
1648d0c080abSJoseph Pusztay -  cellswarm - the cell swarm object
1649d0c080abSJoseph Pusztay 
1650d0c080abSJoseph Pusztay    Level: beginner
1651d0c080abSJoseph Pusztay 
16525627991aSBarry Smith    Note:
16535627991aSBarry Smith     This only supports DMSWARM_PIC types of DMSwarms
1654d0c080abSJoseph Pusztay 
1655db781477SPatrick Sanan .seealso: `DMSwarmGetCellSwarm()`
1656d0c080abSJoseph Pusztay @*/
16579371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm) {
1658d0c080abSJoseph Pusztay   DM        dmc;
1659d0c080abSJoseph Pusztay   PetscInt *pids, particles, p;
1660d0c080abSJoseph Pusztay 
1661d0c080abSJoseph Pusztay   PetscFunctionBegin;
16629566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
16639566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
16649566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
1665d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
166648a46eb9SPierre Jolivet   for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p]));
1667d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
16689566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(cellswarm, &dmc));
16699566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
16709566063dSJacob Faibussowitsch   PetscCall(PetscFree(pids));
1671d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1672d0c080abSJoseph Pusztay }
1673d0c080abSJoseph Pusztay 
1674d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
1675d0c080abSJoseph Pusztay 
16769371c9d4SSatish Balay static PetscErrorCode DMInitialize_Swarm(DM sw) {
1677d0c080abSJoseph Pusztay   PetscFunctionBegin;
1678d0c080abSJoseph Pusztay   sw->dim                           = 0;
1679d0c080abSJoseph Pusztay   sw->ops->view                     = DMView_Swarm;
1680d0c080abSJoseph Pusztay   sw->ops->load                     = NULL;
1681d0c080abSJoseph Pusztay   sw->ops->setfromoptions           = NULL;
1682d0c080abSJoseph Pusztay   sw->ops->clone                    = DMClone_Swarm;
1683d0c080abSJoseph Pusztay   sw->ops->setup                    = DMSetup_Swarm;
1684d0c080abSJoseph Pusztay   sw->ops->createlocalsection       = NULL;
1685d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints = NULL;
1686d0c080abSJoseph Pusztay   sw->ops->createglobalvector       = DMCreateGlobalVector_Swarm;
1687d0c080abSJoseph Pusztay   sw->ops->createlocalvector        = DMCreateLocalVector_Swarm;
1688d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping  = NULL;
1689d0c080abSJoseph Pusztay   sw->ops->createfieldis            = NULL;
1690d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm       = NULL;
1691d0c080abSJoseph Pusztay   sw->ops->getcoloring              = NULL;
1692d0c080abSJoseph Pusztay   sw->ops->creatematrix             = DMCreateMatrix_Swarm;
1693d0c080abSJoseph Pusztay   sw->ops->createinterpolation      = NULL;
1694d0c080abSJoseph Pusztay   sw->ops->createinjection          = NULL;
1695d0c080abSJoseph Pusztay   sw->ops->createmassmatrix         = DMCreateMassMatrix_Swarm;
1696d0c080abSJoseph Pusztay   sw->ops->refine                   = NULL;
1697d0c080abSJoseph Pusztay   sw->ops->coarsen                  = NULL;
1698d0c080abSJoseph Pusztay   sw->ops->refinehierarchy          = NULL;
1699d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy         = NULL;
1700d0c080abSJoseph Pusztay   sw->ops->globaltolocalbegin       = NULL;
1701d0c080abSJoseph Pusztay   sw->ops->globaltolocalend         = NULL;
1702d0c080abSJoseph Pusztay   sw->ops->localtoglobalbegin       = NULL;
1703d0c080abSJoseph Pusztay   sw->ops->localtoglobalend         = NULL;
1704d0c080abSJoseph Pusztay   sw->ops->destroy                  = DMDestroy_Swarm;
1705d0c080abSJoseph Pusztay   sw->ops->createsubdm              = NULL;
1706d0c080abSJoseph Pusztay   sw->ops->getdimpoints             = NULL;
1707d0c080abSJoseph Pusztay   sw->ops->locatepoints             = NULL;
1708d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1709d0c080abSJoseph Pusztay }
1710d0c080abSJoseph Pusztay 
17119371c9d4SSatish Balay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm) {
1712d0c080abSJoseph Pusztay   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1713d0c080abSJoseph Pusztay 
1714d0c080abSJoseph Pusztay   PetscFunctionBegin;
1715d0c080abSJoseph Pusztay   swarm->refct++;
1716d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
17179566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM));
17189566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(*newdm));
17192e56dffeSJoe Pusztay   (*newdm)->dim = dm->dim;
1720d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1721d0c080abSJoseph Pusztay }
1722d0c080abSJoseph Pusztay 
1723d3a51819SDave May /*MC
1724d3a51819SDave May 
1725d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
172662741f57SDave May  This implementation was designed for particle methods in which the underlying
1727d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1728d3a51819SDave May 
172962741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
173062741f57SDave May  To register a field, the user must provide;
173162741f57SDave May  (a) a unique name;
173262741f57SDave May  (b) the data type (or size in bytes);
173362741f57SDave May  (c) the block size of the data.
1734d3a51819SDave May 
1735d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1736c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1737d3a51819SDave May 
173862741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
173962741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
174062741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
174162741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
174262741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
174362741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1744d3a51819SDave May 
1745d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
174662741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1747d3a51819SDave May 
1748d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
17495627991aSBarry Smith  between ranks.
1750d3a51819SDave May 
1751d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1752d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
175362741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1754d3a51819SDave May  fields should be used to define a Vec object via
1755d3a51819SDave May    DMSwarmVectorDefineField()
1756c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1757c215a47eSMatthew Knepley  compatible with different fields to be created.
1758d3a51819SDave May 
175962741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1760d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1761d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1762d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1763d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1764cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1765cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1766d3a51819SDave May 
176762741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
176862741f57SDave May  Please refer to the man page for DMSwarmSetType().
176962741f57SDave May 
1770d3a51819SDave May  Level: beginner
1771d3a51819SDave May 
1772db781477SPatrick Sanan .seealso: `DMType`, `DMCreate()`, `DMSetType()`
1773d3a51819SDave May M*/
17749371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm) {
177557795646SDave May   DM_Swarm *swarm;
177657795646SDave May 
177757795646SDave May   PetscFunctionBegin;
177857795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1779*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&swarm));
1780f0cdbbbaSDave May   dm->data = swarm;
17819566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreate(&swarm->db));
17829566063dSJacob Faibussowitsch   PetscCall(DMSwarmInitializeFieldRegister(dm));
1783d0c080abSJoseph Pusztay   swarm->refct                          = 1;
1784b5bcf523SDave May   swarm->vec_field_set                  = PETSC_FALSE;
17853454631fSDave May   swarm->issetup                        = PETSC_FALSE;
1786480eef7bSDave May   swarm->swarm_type                     = DMSWARM_BASIC;
1787480eef7bSDave May   swarm->migrate_type                   = DMSWARM_MIGRATE_BASIC;
1788480eef7bSDave May   swarm->collect_type                   = DMSWARM_COLLECT_BASIC;
178940c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1790f0cdbbbaSDave May   swarm->dmcell                         = NULL;
1791f0cdbbbaSDave May   swarm->collect_view_active            = PETSC_FALSE;
1792f0cdbbbaSDave May   swarm->collect_view_reset_nlocal      = -1;
17939566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(dm));
17942e956fe4SStefano Zampini   if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId));
179557795646SDave May   PetscFunctionReturn(0);
179657795646SDave May }
1797