xref: /petsc/src/dm/impls/swarm/swarm.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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 
32d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer)
33d71ae5a4SJacob Faibussowitsch {
3474d0cae8SMatthew G. Knepley   DM        dm;
3574d0cae8SMatthew G. Knepley   PetscReal seqval;
3674d0cae8SMatthew G. Knepley   PetscInt  seqnum, bs;
3774d0cae8SMatthew G. Knepley   PetscBool isseq;
3874d0cae8SMatthew G. Knepley 
3974d0cae8SMatthew G. Knepley   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
419566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(v, &bs));
429566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields"));
439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
449566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval));
459566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
469566063dSJacob Faibussowitsch   /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */
479566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
489566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs));
499566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
5074d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
5174d0cae8SMatthew G. Knepley }
5274d0cae8SMatthew G. Knepley 
53d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer)
54d71ae5a4SJacob Faibussowitsch {
5574d0cae8SMatthew G. Knepley   Vec       coordinates;
5674d0cae8SMatthew G. Knepley   PetscInt  Np;
5774d0cae8SMatthew G. Knepley   PetscBool isseq;
5874d0cae8SMatthew G. Knepley 
5974d0cae8SMatthew G. Knepley   PetscFunctionBegin;
609566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetSize(dm, &Np));
619566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates));
629566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
639566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles"));
649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq));
659566063dSJacob Faibussowitsch   PetscCall(VecViewNative(coordinates, viewer));
669566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np));
679566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
689566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates));
6974d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
7074d0cae8SMatthew G. Knepley }
7174d0cae8SMatthew G. Knepley #endif
7274d0cae8SMatthew G. Knepley 
73d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer)
74d71ae5a4SJacob Faibussowitsch {
7574d0cae8SMatthew G. Knepley   DM dm;
76f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
7774d0cae8SMatthew G. Knepley   PetscBool ishdf5;
78f9558f5cSBarry Smith #endif
7974d0cae8SMatthew G. Knepley 
8074d0cae8SMatthew G. Knepley   PetscFunctionBegin;
819566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
8228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
83f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
849566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
8574d0cae8SMatthew G. Knepley   if (ishdf5) {
869566063dSJacob Faibussowitsch     PetscCall(VecView_Swarm_HDF5_Internal(v, viewer));
87f9558f5cSBarry Smith     PetscFunctionReturn(0);
8874d0cae8SMatthew G. Knepley   }
89f9558f5cSBarry Smith #endif
909566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
9174d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
9274d0cae8SMatthew G. Knepley }
9374d0cae8SMatthew G. Knepley 
94d3a51819SDave May /*@C
9562741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
9662741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
9757795646SDave May 
98d083f849SBarry Smith    Collective on dm
9957795646SDave May 
100d3a51819SDave May    Input parameters:
10162741f57SDave May +  dm - a DMSwarm
10262741f57SDave May -  fieldname - the textual name given to a registered field
10357795646SDave May 
104d3a51819SDave May    Level: beginner
10557795646SDave May 
106d3a51819SDave May    Notes:
107e7af74c8SDave May 
10862741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
109e7af74c8SDave May 
110d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
111*d5b43468SJose E. Roman    Multiple calls to DMSwarmVectorDefineField() are permitted.
11257795646SDave May 
113db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
114d3a51819SDave May @*/
115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[])
116d71ae5a4SJacob Faibussowitsch {
117b5bcf523SDave May   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
118b5bcf523SDave May   PetscInt      bs, n;
119b5bcf523SDave May   PetscScalar  *array;
120b5bcf523SDave May   PetscDataType type;
121b5bcf523SDave May 
122a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1239566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
1249566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
1259566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array));
126b5bcf523SDave May 
127b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
12808401ef6SPierre Jolivet   PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
1299566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(swarm->vec_field_name, PETSC_MAX_PATH_LEN - 1, "%s", fieldname));
130b5bcf523SDave May   swarm->vec_field_set    = PETSC_TRUE;
1311b1ea282SDave May   swarm->vec_field_bs     = bs;
132b5bcf523SDave May   swarm->vec_field_nlocal = n;
1339566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, fieldname, &bs, &type, (void **)&array));
134b5bcf523SDave May   PetscFunctionReturn(0);
135b5bcf523SDave May }
136b5bcf523SDave May 
137cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
138d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateGlobalVector_Swarm(DM dm, Vec *vec)
139d71ae5a4SJacob Faibussowitsch {
140b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
141b5bcf523SDave May   Vec       x;
142b5bcf523SDave May   char      name[PETSC_MAX_PATH_LEN];
143b5bcf523SDave May 
144a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1459566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
14628b400f6SJacob Faibussowitsch   PetscCheck(swarm->vec_field_set, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField first");
14708401ef6SPierre 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 */
148cc651181SDave May 
1499566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmField_%s", swarm->vec_field_name));
1509566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &x));
1519566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
1529566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE));
1539566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(x, swarm->vec_field_bs));
1549566063dSJacob Faibussowitsch   PetscCall(VecSetDM(x, dm));
1559566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
1569566063dSJacob Faibussowitsch   PetscCall(VecSetDM(x, dm));
1579566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(x, VECOP_VIEW, (void (*)(void))VecView_Swarm));
158b5bcf523SDave May   *vec = x;
159b5bcf523SDave May   PetscFunctionReturn(0);
160b5bcf523SDave May }
161b5bcf523SDave May 
162b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
163d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateLocalVector_Swarm(DM dm, Vec *vec)
164d71ae5a4SJacob Faibussowitsch {
165b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
166b5bcf523SDave May   Vec       x;
167b5bcf523SDave May   char      name[PETSC_MAX_PATH_LEN];
168b5bcf523SDave May 
169a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1709566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
17128b400f6SJacob Faibussowitsch   PetscCheck(swarm->vec_field_set, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField first");
17208401ef6SPierre 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");
173cc651181SDave May 
1749566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmField_%s", swarm->vec_field_name));
1759566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &x));
1769566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
1779566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE));
1789566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(x, swarm->vec_field_bs));
1799566063dSJacob Faibussowitsch   PetscCall(VecSetDM(x, dm));
1809566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
181b5bcf523SDave May   *vec = x;
182b5bcf523SDave May   PetscFunctionReturn(0);
183b5bcf523SDave May }
184b5bcf523SDave May 
185d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
186d71ae5a4SJacob Faibussowitsch {
187fb1bcc12SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
18877048351SPatrick Sanan   DMSwarmDataField gfield;
1892e956fe4SStefano Zampini   PetscInt         bs, nlocal, fid = -1, cfid = -2;
1902e956fe4SStefano Zampini   PetscBool        flg;
191d3a51819SDave May 
192fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
1932e956fe4SStefano Zampini   /* check vector is an inplace array */
1942e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
1952e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg));
1962e956fe4SStefano 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);
1979566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(*vec, &nlocal));
1989566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(*vec, &bs));
19908401ef6SPierre 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");
2009566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
2019566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
2028df78e51SMark Adams   PetscCall(VecResetArray(*vec));
2039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(vec));
204fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
205fb1bcc12SMatthew G. Knepley }
206fb1bcc12SMatthew G. Knepley 
207d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
208d71ae5a4SJacob Faibussowitsch {
209fb1bcc12SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
210fb1bcc12SMatthew G. Knepley   PetscDataType type;
211fb1bcc12SMatthew G. Knepley   PetscScalar  *array;
2122e956fe4SStefano Zampini   PetscInt      bs, n, fid;
213fb1bcc12SMatthew G. Knepley   char          name[PETSC_MAX_PATH_LEN];
214e4fbd051SBarry Smith   PetscMPIInt   size;
2158df78e51SMark Adams   PetscBool     iscuda, iskokkos;
216fb1bcc12SMatthew G. Knepley 
217fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
2189566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
2199566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
2209566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array));
22108401ef6SPierre Jolivet   PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
222fb1bcc12SMatthew G. Knepley 
2239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2248df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos));
2258df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda));
2268df78e51SMark Adams   PetscCall(VecCreate(comm, vec));
2278df78e51SMark Adams   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
2288df78e51SMark Adams   PetscCall(VecSetBlockSize(*vec, bs));
2298df78e51SMark Adams   if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS));
2308df78e51SMark Adams   else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA));
2318df78e51SMark Adams   else PetscCall(VecSetType(*vec, VECSTANDARD));
2328df78e51SMark Adams   PetscCall(VecPlaceArray(*vec, array));
2338df78e51SMark Adams 
2349566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname));
2359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
236fb1bcc12SMatthew G. Knepley 
237fb1bcc12SMatthew G. Knepley   /* Set guard */
2382e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
2392e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid));
24074d0cae8SMatthew G. Knepley 
2419566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*vec, dm));
2429566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm));
243fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
244fb1bcc12SMatthew G. Knepley }
245fb1bcc12SMatthew G. Knepley 
2460643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
2470643ed39SMatthew G. Knepley 
2480643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
2490643ed39SMatthew G. Knepley 
2500643ed39SMatthew G. Knepley    and a particle function is given by
2510643ed39SMatthew G. Knepley 
2520643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
2530643ed39SMatthew G. Knepley 
2540643ed39SMatthew G. Knepley    then we want to require that
2550643ed39SMatthew G. Knepley 
2560643ed39SMatthew G. Knepley      M \hat f = M_p f
2570643ed39SMatthew G. Knepley 
2580643ed39SMatthew G. Knepley    where the particle mass matrix is given by
2590643ed39SMatthew G. Knepley 
2600643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
2610643ed39SMatthew G. Knepley 
2620643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
2630643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
2640643ed39SMatthew G. Knepley */
265d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
266d71ae5a4SJacob Faibussowitsch {
26783c47955SMatthew G. Knepley   const char  *name = "Mass Matrix";
2680643ed39SMatthew G. Knepley   MPI_Comm     comm;
26983c47955SMatthew G. Knepley   PetscDS      prob;
27083c47955SMatthew G. Knepley   PetscSection fsection, globalFSection;
271e8f14785SLisandro Dalcin   PetscHSetIJ  ht;
2720643ed39SMatthew G. Knepley   PetscLayout  rLayout, colLayout;
27383c47955SMatthew G. Knepley   PetscInt    *dnz, *onz;
274adb2528bSMark Adams   PetscInt     locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
2750643ed39SMatthew G. Knepley   PetscReal   *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
27683c47955SMatthew G. Knepley   PetscScalar *elemMat;
2770643ed39SMatthew G. Knepley   PetscInt     dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
27883c47955SMatthew G. Knepley 
27983c47955SMatthew G. Knepley   PetscFunctionBegin;
2809566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
2819566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &dim));
2829566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
2839566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
2849566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
2859566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ));
2869566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
2879566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
2889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
2899566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
29083c47955SMatthew G. Knepley 
2919566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
2929566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
2939566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
2949566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
2959566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
2969566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
2970643ed39SMatthew G. Knepley 
2989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
2999566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
3009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
3019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
3029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
3039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
3040643ed39SMatthew G. Knepley 
3059566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
3069566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
30753e60ab4SJoseph Pusztay 
3089566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
3090643ed39SMatthew G. Knepley   /* count non-zeros */
3109566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
31183c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
31283c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
3130643ed39SMatthew G. Knepley       PetscInt  c, i;
3140643ed39SMatthew G. Knepley       PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */
31583c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
31683c47955SMatthew G. Knepley 
3179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3189566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
319fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
32083c47955SMatthew G. Knepley       {
321e8f14785SLisandro Dalcin         PetscHashIJKey key;
322e8f14785SLisandro Dalcin         PetscBool      missing;
32383c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
324adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
325adb2528bSMark Adams           if (key.j >= 0) {
32683c47955SMatthew G. Knepley             /* Get indices for coarse elements */
32783c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
328adb2528bSMark Adams               key.i = cindices[c] + rStart; /* global cols (from Swarm) */
329adb2528bSMark Adams               if (key.i < 0) continue;
3309566063dSJacob Faibussowitsch               PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
33183c47955SMatthew G. Knepley               if (missing) {
3320643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
333e8f14785SLisandro Dalcin                 else ++onz[key.i - rStart];
33463a3b9bcSJacob Faibussowitsch               } else SETERRQ(PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j);
33583c47955SMatthew G. Knepley             }
336fc7c92abSMatthew G. Knepley           }
337fc7c92abSMatthew G. Knepley         }
3389566063dSJacob Faibussowitsch         PetscCall(PetscFree(cindices));
33983c47955SMatthew G. Knepley       }
3409566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
34183c47955SMatthew G. Knepley     }
34283c47955SMatthew G. Knepley   }
3439566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
3449566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
3459566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
3469566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
3479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(maxC * totDim, &elemMat, maxC, &rowIDXs, maxC * dim, &xi));
34883c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
349ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
35083c47955SMatthew G. Knepley     PetscObject     obj;
351ef0bb6c7SMatthew G. Knepley     PetscReal      *coords;
3520643ed39SMatthew G. Knepley     PetscInt        Nc, i;
35383c47955SMatthew G. Knepley 
3549566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
3559566063dSJacob Faibussowitsch     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
35663a3b9bcSJacob Faibussowitsch     PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc);
3579566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
35883c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
35983c47955SMatthew G. Knepley       PetscInt *findices, *cindices;
36083c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
3610643ed39SMatthew G. Knepley       PetscInt  p, c;
36283c47955SMatthew G. Knepley 
3630643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
3649566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
3659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3669566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
367ad540459SPierre Jolivet       for (p = 0; p < numCIndices; ++p) CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &coords[cindices[p] * dim], &xi[p * dim]);
3689566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
36983c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
3709566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elemMat, numCIndices * totDim));
37183c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
3720643ed39SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
3730643ed39SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
3740643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
375ef0bb6c7SMatthew G. Knepley             elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
37683c47955SMatthew G. Knepley           }
3770643ed39SMatthew G. Knepley         }
3780643ed39SMatthew G. Knepley       }
379adb2528bSMark Adams       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
3809566063dSJacob Faibussowitsch       if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
3819566063dSJacob Faibussowitsch       PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES));
3829566063dSJacob Faibussowitsch       PetscCall(PetscFree(cindices));
3839566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
3849566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
38583c47955SMatthew G. Knepley     }
3869566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
38783c47955SMatthew G. Knepley   }
3889566063dSJacob Faibussowitsch   PetscCall(PetscFree3(elemMat, rowIDXs, xi));
3899566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
3909566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
3919566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
3929566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
39383c47955SMatthew G. Knepley   PetscFunctionReturn(0);
39483c47955SMatthew G. Knepley }
39583c47955SMatthew G. Knepley 
396d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */
397d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m)
398d71ae5a4SJacob Faibussowitsch {
399d0c080abSJoseph Pusztay   Vec      field;
400d0c080abSJoseph Pusztay   PetscInt size;
401d0c080abSJoseph Pusztay 
402d0c080abSJoseph Pusztay   PetscFunctionBegin;
4039566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(sw, &field));
4049566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(field, &size));
4059566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(sw, &field));
4069566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, m));
4079566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*m));
4089566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size));
4099566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL));
4109566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(*m));
4119566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY));
4129566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY));
4139566063dSJacob Faibussowitsch   PetscCall(MatShift(*m, 1.0));
4149566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*m, sw));
415d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
416d0c080abSJoseph Pusztay }
417d0c080abSJoseph Pusztay 
418adb2528bSMark Adams /* FEM cols, Particle rows */
419d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
420d71ae5a4SJacob Faibussowitsch {
421895a1698SMatthew G. Knepley   PetscSection gsf;
42283c47955SMatthew G. Knepley   PetscInt     m, n;
42383c47955SMatthew G. Knepley   void        *ctx;
42483c47955SMatthew G. Knepley 
42583c47955SMatthew G. Knepley   PetscFunctionBegin;
4269566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
4279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
4289566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dmCoarse, &n));
4299566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
4309566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE));
4319566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
4329566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
43383c47955SMatthew G. Knepley 
4349566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
4359566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
43683c47955SMatthew G. Knepley   PetscFunctionReturn(0);
43783c47955SMatthew G. Knepley }
43883c47955SMatthew G. Knepley 
439d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
440d71ae5a4SJacob Faibussowitsch {
4414cc7f7b2SMatthew G. Knepley   const char  *name = "Mass Matrix Square";
4424cc7f7b2SMatthew G. Knepley   MPI_Comm     comm;
4434cc7f7b2SMatthew G. Knepley   PetscDS      prob;
4444cc7f7b2SMatthew G. Knepley   PetscSection fsection, globalFSection;
4454cc7f7b2SMatthew G. Knepley   PetscHSetIJ  ht;
4464cc7f7b2SMatthew G. Knepley   PetscLayout  rLayout, colLayout;
4474cc7f7b2SMatthew G. Knepley   PetscInt    *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
4484cc7f7b2SMatthew G. Knepley   PetscInt     locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4494cc7f7b2SMatthew G. Knepley   PetscReal   *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
4504cc7f7b2SMatthew G. Knepley   PetscScalar *elemMat, *elemMatSq;
4514cc7f7b2SMatthew G. Knepley   PetscInt     cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
4524cc7f7b2SMatthew G. Knepley 
4534cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
4549566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
4559566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &cdim));
4569566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
4579566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
4589566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
4599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ));
4609566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
4619566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
4629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
4639566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
4644cc7f7b2SMatthew G. Knepley 
4659566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
4669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
4679566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
4689566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
4699566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
4709566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
4714cc7f7b2SMatthew G. Knepley 
4729566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
4739566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
4749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
4759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
4769566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
4779566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
4784cc7f7b2SMatthew G. Knepley 
4799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmf, &depth));
4809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize));
4814cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth);
4829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxAdjSize, &adj));
4834cc7f7b2SMatthew G. Knepley 
4849566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
4859566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
4864cc7f7b2SMatthew G. Knepley   /* Count nonzeros
4874cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
4884cc7f7b2SMatthew G. Knepley   */
4899566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
4904cc7f7b2SMatthew G. Knepley   for (cell = cStart; cell < cEnd; ++cell) {
4914cc7f7b2SMatthew G. Knepley     PetscInt  i;
4924cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
4934cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
4944cc7f7b2SMatthew G. Knepley #if 0
4954cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
4964cc7f7b2SMatthew G. Knepley #endif
4974cc7f7b2SMatthew G. Knepley 
4989566063dSJacob Faibussowitsch     PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
4994cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
5004cc7f7b2SMatthew G. Knepley     /* Diagonal block */
501ad540459SPierre Jolivet     for (i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices;
5024cc7f7b2SMatthew G. Knepley #if 0
5034cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
5049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj));
5054cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
5064cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
5074cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
5084cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
5094cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
5104cc7f7b2SMatthew G. Knepley 
5119566063dSJacob Faibussowitsch         PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
5124cc7f7b2SMatthew G. Knepley         {
5134cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
5144cc7f7b2SMatthew G. Knepley           PetscBool      missing;
5154cc7f7b2SMatthew G. Knepley 
5164cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
5174cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
5184cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
5194cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
5204cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
5214cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
5229566063dSJacob Faibussowitsch               PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
5234cc7f7b2SMatthew G. Knepley               if (missing) {
5244cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
5254cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
5264cc7f7b2SMatthew G. Knepley               }
5274cc7f7b2SMatthew G. Knepley             }
5284cc7f7b2SMatthew G. Knepley           }
5294cc7f7b2SMatthew G. Knepley         }
5309566063dSJacob Faibussowitsch         PetscCall(PetscFree(ncindices));
5314cc7f7b2SMatthew G. Knepley       }
5324cc7f7b2SMatthew G. Knepley     }
5334cc7f7b2SMatthew G. Knepley #endif
5349566063dSJacob Faibussowitsch     PetscCall(PetscFree(cindices));
5354cc7f7b2SMatthew G. Knepley   }
5369566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
5379566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
5389566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
5399566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
5409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi));
5414cc7f7b2SMatthew G. Knepley   /* Fill in values
5424cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
5434cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
5444cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
5454cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
5464cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
5474cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
5484cc7f7b2SMatthew G. Knepley          Insert block
5494cc7f7b2SMatthew G. Knepley   */
5504cc7f7b2SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
5514cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
5524cc7f7b2SMatthew G. Knepley     PetscObject     obj;
5534cc7f7b2SMatthew G. Knepley     PetscReal      *coords;
5544cc7f7b2SMatthew G. Knepley     PetscInt        Nc, i;
5554cc7f7b2SMatthew G. Knepley 
5569566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5579566063dSJacob Faibussowitsch     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
55863a3b9bcSJacob Faibussowitsch     PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc);
5599566063dSJacob Faibussowitsch     PetscCall(DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
5604cc7f7b2SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
5614cc7f7b2SMatthew G. Knepley       PetscInt *findices, *cindices;
5624cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
5634cc7f7b2SMatthew G. Knepley       PetscInt  p, c;
5644cc7f7b2SMatthew G. Knepley 
5654cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5669566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
5679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5689566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
569ad540459SPierre Jolivet       for (p = 0; p < numCIndices; ++p) CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p] * cdim], &xi[p * cdim]);
5709566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
5714cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
5729566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elemMat, numCIndices * totDim));
5734cc7f7b2SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
5744cc7f7b2SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
5754cc7f7b2SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
5764cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
5774cc7f7b2SMatthew G. Knepley             elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
5784cc7f7b2SMatthew G. Knepley           }
5794cc7f7b2SMatthew G. Knepley         }
5804cc7f7b2SMatthew G. Knepley       }
5819566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
5824cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
5839566063dSJacob Faibussowitsch       if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
5844cc7f7b2SMatthew G. Knepley       /* Block diagonal */
58578884ca7SMatthew G. Knepley       if (numCIndices) {
5864cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
5874cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
5884cc7f7b2SMatthew G. Knepley 
5899566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numCIndices, &blasn));
5909566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numFIndices, &blask));
591792fecdfSBarry Smith         PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn));
5924cc7f7b2SMatthew G. Knepley       }
5939566063dSJacob Faibussowitsch       PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES));
5944cc7f7b2SMatthew G. Knepley       /* TODO Off-diagonal */
5959566063dSJacob Faibussowitsch       PetscCall(PetscFree(cindices));
5969566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5974cc7f7b2SMatthew G. Knepley     }
5989566063dSJacob Faibussowitsch     PetscCall(DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
5994cc7f7b2SMatthew G. Knepley   }
6009566063dSJacob Faibussowitsch   PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi));
6019566063dSJacob Faibussowitsch   PetscCall(PetscFree(adj));
6029566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
6039566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
6049566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
6059566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
6064cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6074cc7f7b2SMatthew G. Knepley }
6084cc7f7b2SMatthew G. Knepley 
6094cc7f7b2SMatthew G. Knepley /*@C
6104cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
6114cc7f7b2SMatthew G. Knepley 
6124cc7f7b2SMatthew G. Knepley   Collective on dmCoarse
6134cc7f7b2SMatthew G. Knepley 
6144cc7f7b2SMatthew G. Knepley   Input parameters:
6154cc7f7b2SMatthew G. Knepley + dmCoarse - a DMSwarm
6164cc7f7b2SMatthew G. Knepley - dmFine   - a DMPlex
6174cc7f7b2SMatthew G. Knepley 
6184cc7f7b2SMatthew G. Knepley   Output parameter:
6194cc7f7b2SMatthew G. Knepley . mass     - the square of the particle mass matrix
6204cc7f7b2SMatthew G. Knepley 
6214cc7f7b2SMatthew G. Knepley   Level: advanced
6224cc7f7b2SMatthew G. Knepley 
6234cc7f7b2SMatthew G. Knepley   Notes:
6244cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
6254cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
6264cc7f7b2SMatthew G. Knepley 
627db781477SPatrick Sanan .seealso: `DMCreateMassMatrix()`
6284cc7f7b2SMatthew G. Knepley @*/
629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
630d71ae5a4SJacob Faibussowitsch {
6314cc7f7b2SMatthew G. Knepley   PetscInt n;
6324cc7f7b2SMatthew G. Knepley   void    *ctx;
6334cc7f7b2SMatthew G. Knepley 
6344cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dmCoarse, &n));
6369566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
6379566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE));
6389566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
6399566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
6404cc7f7b2SMatthew G. Knepley 
6419566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
6429566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view"));
6434cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6444cc7f7b2SMatthew G. Knepley }
6454cc7f7b2SMatthew G. Knepley 
646fb1bcc12SMatthew G. Knepley /*@C
647d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
648d3a51819SDave May 
649d083f849SBarry Smith    Collective on dm
650d3a51819SDave May 
651d3a51819SDave May    Input parameters:
65262741f57SDave May +  dm - a DMSwarm
65362741f57SDave May -  fieldname - the textual name given to a registered field
654d3a51819SDave May 
6558b8a3813SDave May    Output parameter:
656d3a51819SDave May .  vec - the vector
657d3a51819SDave May 
658d3a51819SDave May    Level: beginner
659d3a51819SDave May 
6608b8a3813SDave May    Notes:
6618b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
6628b8a3813SDave May 
663db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()`
664d3a51819SDave May @*/
665d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
666d71ae5a4SJacob Faibussowitsch {
667fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
668b5bcf523SDave May 
669fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
6709566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
671b5bcf523SDave May   PetscFunctionReturn(0);
672b5bcf523SDave May }
673b5bcf523SDave May 
674d3a51819SDave May /*@C
675d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
676d3a51819SDave May 
677d083f849SBarry Smith    Collective on dm
678d3a51819SDave May 
679d3a51819SDave May    Input parameters:
68062741f57SDave May +  dm - a DMSwarm
68162741f57SDave May -  fieldname - the textual name given to a registered field
682d3a51819SDave May 
6838b8a3813SDave May    Output parameter:
684d3a51819SDave May .  vec - the vector
685d3a51819SDave May 
686d3a51819SDave May    Level: beginner
687d3a51819SDave May 
688db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
689d3a51819SDave May @*/
690d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
691d71ae5a4SJacob Faibussowitsch {
692fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
6939566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
694b5bcf523SDave May   PetscFunctionReturn(0);
695b5bcf523SDave May }
696b5bcf523SDave May 
697fb1bcc12SMatthew G. Knepley /*@C
698fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
699fb1bcc12SMatthew G. Knepley 
700d083f849SBarry Smith    Collective on dm
701fb1bcc12SMatthew G. Knepley 
702fb1bcc12SMatthew G. Knepley    Input parameters:
70362741f57SDave May +  dm - a DMSwarm
70462741f57SDave May -  fieldname - the textual name given to a registered field
705fb1bcc12SMatthew G. Knepley 
7068b8a3813SDave May    Output parameter:
707fb1bcc12SMatthew G. Knepley .  vec - the vector
708fb1bcc12SMatthew G. Knepley 
709fb1bcc12SMatthew G. Knepley    Level: beginner
710fb1bcc12SMatthew G. Knepley 
7118b8a3813SDave May    Notes:
7128b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
7138b8a3813SDave May 
714db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
715fb1bcc12SMatthew G. Knepley @*/
716d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
717d71ae5a4SJacob Faibussowitsch {
718fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
719bbe8250bSMatthew G. Knepley 
720fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
7219566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
722fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
723bbe8250bSMatthew G. Knepley }
724fb1bcc12SMatthew G. Knepley 
725fb1bcc12SMatthew G. Knepley /*@C
726fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
727fb1bcc12SMatthew G. Knepley 
728d083f849SBarry Smith    Collective on dm
729fb1bcc12SMatthew G. Knepley 
730fb1bcc12SMatthew G. Knepley    Input parameters:
73162741f57SDave May +  dm - a DMSwarm
73262741f57SDave May -  fieldname - the textual name given to a registered field
733fb1bcc12SMatthew G. Knepley 
7348b8a3813SDave May    Output parameter:
735fb1bcc12SMatthew G. Knepley .  vec - the vector
736fb1bcc12SMatthew G. Knepley 
737fb1bcc12SMatthew G. Knepley    Level: beginner
738fb1bcc12SMatthew G. Knepley 
739db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()`
740fb1bcc12SMatthew G. Knepley @*/
741d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
742d71ae5a4SJacob Faibussowitsch {
743fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
7449566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
745bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
746bbe8250bSMatthew G. Knepley }
747bbe8250bSMatthew G. Knepley 
748d3a51819SDave May /*@C
749d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
750d3a51819SDave May 
751d083f849SBarry Smith    Collective on dm
752d3a51819SDave May 
753d3a51819SDave May    Input parameter:
754d3a51819SDave May .  dm - a DMSwarm
755d3a51819SDave May 
756d3a51819SDave May    Level: beginner
757d3a51819SDave May 
758d3a51819SDave May    Notes:
7598b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
760d3a51819SDave May 
761db781477SPatrick Sanan .seealso: `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
762db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
763d3a51819SDave May @*/
764d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
765d71ae5a4SJacob Faibussowitsch {
7665f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
7673454631fSDave May 
768521f74f9SMatthew G. Knepley   PetscFunctionBegin;
769cc651181SDave May   if (!swarm->field_registration_initialized) {
7705f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
7719566063dSJacob Faibussowitsch     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifer */
7729566063dSJacob Faibussowitsch     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT));  /* used for communication */
773cc651181SDave May   }
7745f50eb2eSDave May   PetscFunctionReturn(0);
7755f50eb2eSDave May }
7765f50eb2eSDave May 
77774d0cae8SMatthew G. Knepley /*@
778d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
779d3a51819SDave May 
780d083f849SBarry Smith    Collective on dm
781d3a51819SDave May 
782d3a51819SDave May    Input parameter:
783d3a51819SDave May .  dm - a DMSwarm
784d3a51819SDave May 
785d3a51819SDave May    Level: beginner
786d3a51819SDave May 
787d3a51819SDave May    Notes:
78862741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
789d3a51819SDave May 
790db781477SPatrick Sanan .seealso: `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
791db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
792d3a51819SDave May @*/
793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
794d71ae5a4SJacob Faibussowitsch {
7955f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
7966845f8f5SDave May 
797521f74f9SMatthew G. Knepley   PetscFunctionBegin;
79848a46eb9SPierre Jolivet   if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db));
799f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
8005f50eb2eSDave May   PetscFunctionReturn(0);
8015f50eb2eSDave May }
8025f50eb2eSDave May 
80374d0cae8SMatthew G. Knepley /*@
804d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
805d3a51819SDave May 
806d3a51819SDave May    Not collective
807d3a51819SDave May 
808d3a51819SDave May    Input parameters:
80962741f57SDave May +  dm - a DMSwarm
810d3a51819SDave May .  nlocal - the length of each registered field
81162741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
812d3a51819SDave May 
813d3a51819SDave May    Level: beginner
814d3a51819SDave May 
815db781477SPatrick Sanan .seealso: `DMSwarmGetLocalSize()`
816d3a51819SDave May @*/
817d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetLocalSizes(DM dm, PetscInt nlocal, PetscInt buffer)
818d71ae5a4SJacob Faibussowitsch {
8195f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
8205f50eb2eSDave May 
821521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0));
8239566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer));
8249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0));
8255f50eb2eSDave May   PetscFunctionReturn(0);
8265f50eb2eSDave May }
8275f50eb2eSDave May 
82874d0cae8SMatthew G. Knepley /*@
829*d5b43468SJose E. Roman    DMSwarmSetCellDM - Attaches a DM to a DMSwarm
830d3a51819SDave May 
831d083f849SBarry Smith    Collective on dm
832d3a51819SDave May 
833d3a51819SDave May    Input parameters:
83462741f57SDave May +  dm - a DMSwarm
83562741f57SDave May -  dmcell - the DM to attach to the DMSwarm
836d3a51819SDave May 
837d3a51819SDave May    Level: beginner
838d3a51819SDave May 
839d3a51819SDave May    Notes:
840d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
8418b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
842d3a51819SDave May 
843db781477SPatrick Sanan .seealso: `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()`
844d3a51819SDave May @*/
845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetCellDM(DM dm, DM dmcell)
846d71ae5a4SJacob Faibussowitsch {
847b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
848521f74f9SMatthew G. Knepley 
849521f74f9SMatthew G. Knepley   PetscFunctionBegin;
850b16650c8SDave May   swarm->dmcell = dmcell;
851b16650c8SDave May   PetscFunctionReturn(0);
852b16650c8SDave May }
853b16650c8SDave May 
85474d0cae8SMatthew G. Knepley /*@
855d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
856d3a51819SDave May 
857d083f849SBarry Smith    Collective on dm
858d3a51819SDave May 
859d3a51819SDave May    Input parameter:
860d3a51819SDave May .  dm - a DMSwarm
861d3a51819SDave May 
862d3a51819SDave May    Output parameter:
863d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
864d3a51819SDave May 
865d3a51819SDave May    Level: beginner
866d3a51819SDave May 
867db781477SPatrick Sanan .seealso: `DMSwarmSetCellDM()`
868d3a51819SDave May @*/
869d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetCellDM(DM dm, DM *dmcell)
870d71ae5a4SJacob Faibussowitsch {
871fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
872521f74f9SMatthew G. Knepley 
873521f74f9SMatthew G. Knepley   PetscFunctionBegin;
874fe39f135SDave May   *dmcell = swarm->dmcell;
875fe39f135SDave May   PetscFunctionReturn(0);
876fe39f135SDave May }
877fe39f135SDave May 
87874d0cae8SMatthew G. Knepley /*@
879*d5b43468SJose E. Roman    DMSwarmGetLocalSize - Retrieves the local length of fields registered
880d3a51819SDave May 
881d3a51819SDave May    Not collective
882d3a51819SDave May 
883d3a51819SDave May    Input parameter:
884d3a51819SDave May .  dm - a DMSwarm
885d3a51819SDave May 
886d3a51819SDave May    Output parameter:
887d3a51819SDave May .  nlocal - the length of each registered field
888d3a51819SDave May 
889d3a51819SDave May    Level: beginner
890d3a51819SDave May 
891db781477SPatrick Sanan .seealso: `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()`
892d3a51819SDave May @*/
893d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal)
894d71ae5a4SJacob Faibussowitsch {
895dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
896dcf43ee8SDave May 
897521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8989566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL));
899dcf43ee8SDave May   PetscFunctionReturn(0);
900dcf43ee8SDave May }
901dcf43ee8SDave May 
90274d0cae8SMatthew G. Knepley /*@
903*d5b43468SJose E. Roman    DMSwarmGetSize - Retrieves the total length of fields registered
904d3a51819SDave May 
905d083f849SBarry Smith    Collective on dm
906d3a51819SDave May 
907d3a51819SDave May    Input parameter:
908d3a51819SDave May .  dm - a DMSwarm
909d3a51819SDave May 
910d3a51819SDave May    Output parameter:
911d3a51819SDave May .  n - the total length of each registered field
912d3a51819SDave May 
913d3a51819SDave May    Level: beginner
914d3a51819SDave May 
915d3a51819SDave May    Note:
916d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
917d3a51819SDave May 
918db781477SPatrick Sanan .seealso: `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()`
919d3a51819SDave May @*/
920d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n)
921d71ae5a4SJacob Faibussowitsch {
922dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
9235627991aSBarry Smith   PetscInt  nlocal;
924dcf43ee8SDave May 
925521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9269566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
9279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
928dcf43ee8SDave May   PetscFunctionReturn(0);
929dcf43ee8SDave May }
930dcf43ee8SDave May 
931d3a51819SDave May /*@C
9328b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
933d3a51819SDave May 
934d083f849SBarry Smith    Collective on dm
935d3a51819SDave May 
936d3a51819SDave May    Input parameters:
93762741f57SDave May +  dm - a DMSwarm
938d3a51819SDave May .  fieldname - the textual name to identify this field
939d3a51819SDave May .  blocksize - the number of each data type
94062741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
941d3a51819SDave May 
942d3a51819SDave May    Level: beginner
943d3a51819SDave May 
944d3a51819SDave May    Notes:
9458b8a3813SDave May    The textual name for each registered field must be unique.
946d3a51819SDave May 
947db781477SPatrick Sanan .seealso: `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
948d3a51819SDave May @*/
949d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type)
950d71ae5a4SJacob Faibussowitsch {
951b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
952b62e03f8SDave May   size_t    size;
953b62e03f8SDave May 
954521f74f9SMatthew G. Knepley   PetscFunctionBegin;
95528b400f6SJacob Faibussowitsch   PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first");
95628b400f6SJacob Faibussowitsch   PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
9575f50eb2eSDave May 
95808401ef6SPierre Jolivet   PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
95908401ef6SPierre Jolivet   PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
96008401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
96108401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
96208401ef6SPierre Jolivet   PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
963b62e03f8SDave May 
9649566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &size));
965b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
9669566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL));
96752c3ed93SDave May   {
96877048351SPatrick Sanan     DMSwarmDataField gfield;
96952c3ed93SDave May 
9709566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
9719566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
97252c3ed93SDave May   }
973b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = type;
974b62e03f8SDave May   PetscFunctionReturn(0);
975b62e03f8SDave May }
976b62e03f8SDave May 
977d3a51819SDave May /*@C
978d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
979d3a51819SDave May 
980d083f849SBarry Smith    Collective on dm
981d3a51819SDave May 
982d3a51819SDave May    Input parameters:
98362741f57SDave May +  dm - a DMSwarm
984d3a51819SDave May .  fieldname - the textual name to identify this field
98562741f57SDave May -  size - the size in bytes of the user struct of each data type
986d3a51819SDave May 
987d3a51819SDave May    Level: beginner
988d3a51819SDave May 
989d3a51819SDave May    Notes:
9908b8a3813SDave May    The textual name for each registered field must be unique.
991d3a51819SDave May 
992db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()`
993d3a51819SDave May @*/
994d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size)
995d71ae5a4SJacob Faibussowitsch {
996b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
997b62e03f8SDave May 
998521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9999566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL));
1000b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT;
1001b62e03f8SDave May   PetscFunctionReturn(0);
1002b62e03f8SDave May }
1003b62e03f8SDave May 
1004d3a51819SDave May /*@C
1005d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
1006d3a51819SDave May 
1007d083f849SBarry Smith    Collective on dm
1008d3a51819SDave May 
1009d3a51819SDave May    Input parameters:
101062741f57SDave May +  dm - a DMSwarm
1011d3a51819SDave May .  fieldname - the textual name to identify this field
1012d3a51819SDave May .  size - the size in bytes of the user data type
101362741f57SDave May -  blocksize - the number of each data type
1014d3a51819SDave May 
1015d3a51819SDave May    Level: beginner
1016d3a51819SDave May 
1017d3a51819SDave May    Notes:
10188b8a3813SDave May    The textual name for each registered field must be unique.
1019d3a51819SDave May 
1020db781477SPatrick Sanan .seealso: `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1021d3a51819SDave May @*/
1022d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize)
1023d71ae5a4SJacob Faibussowitsch {
1024b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1025b62e03f8SDave May 
1026521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10279566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL));
1028320740a0SDave May   {
102977048351SPatrick Sanan     DMSwarmDataField gfield;
1030320740a0SDave May 
10319566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
10329566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
1033320740a0SDave May   }
1034b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
1035b62e03f8SDave May   PetscFunctionReturn(0);
1036b62e03f8SDave May }
1037b62e03f8SDave May 
1038d3a51819SDave May /*@C
1039d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1040d3a51819SDave May 
1041d3a51819SDave May    Not collective
1042d3a51819SDave May 
1043d3a51819SDave May    Input parameters:
104462741f57SDave May +  dm - a DMSwarm
104562741f57SDave May -  fieldname - the textual name to identify this field
1046d3a51819SDave May 
1047d3a51819SDave May    Output parameters:
104862741f57SDave May +  blocksize - the number of each data type
1049d3a51819SDave May .  type - the data type
105062741f57SDave May -  data - pointer to raw array
1051d3a51819SDave May 
1052d3a51819SDave May    Level: beginner
1053d3a51819SDave May 
1054d3a51819SDave May    Notes:
10558b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
1056d3a51819SDave May 
1057db781477SPatrick Sanan .seealso: `DMSwarmRestoreField()`
1058d3a51819SDave May @*/
1059d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data)
1060d71ae5a4SJacob Faibussowitsch {
1061b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
106277048351SPatrick Sanan   DMSwarmDataField gfield;
1063b62e03f8SDave May 
1064521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10659566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
10669566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
10679566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetAccess(gfield));
10689566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetEntries(gfield, data));
1069ad540459SPierre Jolivet   if (blocksize) *blocksize = gfield->bs;
1070ad540459SPierre Jolivet   if (type) *type = gfield->petsc_type;
1071b62e03f8SDave May   PetscFunctionReturn(0);
1072b62e03f8SDave May }
1073b62e03f8SDave May 
1074d3a51819SDave May /*@C
1075d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1076d3a51819SDave May 
1077d3a51819SDave May    Not collective
1078d3a51819SDave May 
1079d3a51819SDave May    Input parameters:
108062741f57SDave May +  dm - a DMSwarm
108162741f57SDave May -  fieldname - the textual name to identify this field
1082d3a51819SDave May 
1083d3a51819SDave May    Output parameters:
108462741f57SDave May +  blocksize - the number of each data type
1085d3a51819SDave May .  type - the data type
108662741f57SDave May -  data - pointer to raw array
1087d3a51819SDave May 
1088d3a51819SDave May    Level: beginner
1089d3a51819SDave May 
1090d3a51819SDave May    Notes:
10918b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
1092d3a51819SDave May 
1093db781477SPatrick Sanan .seealso: `DMSwarmGetField()`
1094d3a51819SDave May @*/
1095d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data)
1096d71ae5a4SJacob Faibussowitsch {
1097b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
109877048351SPatrick Sanan   DMSwarmDataField gfield;
1099b62e03f8SDave May 
1100521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11019566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
11029566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
1103b62e03f8SDave May   if (data) *data = NULL;
1104b62e03f8SDave May   PetscFunctionReturn(0);
1105b62e03f8SDave May }
1106b62e03f8SDave May 
110774d0cae8SMatthew G. Knepley /*@
1108d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
1109d3a51819SDave May 
1110d3a51819SDave May    Not collective
1111d3a51819SDave May 
1112d3a51819SDave May    Input parameter:
1113d3a51819SDave May .  dm - a DMSwarm
1114d3a51819SDave May 
1115d3a51819SDave May    Level: beginner
1116d3a51819SDave May 
1117d3a51819SDave May    Notes:
11188b8a3813SDave May    The new point will have all fields initialized to zero.
1119d3a51819SDave May 
1120db781477SPatrick Sanan .seealso: `DMSwarmAddNPoints()`
1121d3a51819SDave May @*/
1122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddPoint(DM dm)
1123d71ae5a4SJacob Faibussowitsch {
1124cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1125cb1d1399SDave May 
1126521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11279566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
11289566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
11299566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketAddPoint(swarm->db));
11309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
1131cb1d1399SDave May   PetscFunctionReturn(0);
1132cb1d1399SDave May }
1133cb1d1399SDave May 
113474d0cae8SMatthew G. Knepley /*@
1135d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
1136d3a51819SDave May 
1137d3a51819SDave May    Not collective
1138d3a51819SDave May 
1139d3a51819SDave May    Input parameters:
114062741f57SDave May +  dm - a DMSwarm
114162741f57SDave May -  npoints - the number of new points to add
1142d3a51819SDave May 
1143d3a51819SDave May    Level: beginner
1144d3a51819SDave May 
1145d3a51819SDave May    Notes:
11468b8a3813SDave May    The new point will have all fields initialized to zero.
1147d3a51819SDave May 
1148db781477SPatrick Sanan .seealso: `DMSwarmAddPoint()`
1149d3a51819SDave May @*/
1150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints)
1151d71ae5a4SJacob Faibussowitsch {
1152cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1153cb1d1399SDave May   PetscInt  nlocal;
1154cb1d1399SDave May 
1155521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
11579566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1158cb1d1399SDave May   nlocal = nlocal + npoints;
11599566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
11609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
1161cb1d1399SDave May   PetscFunctionReturn(0);
1162cb1d1399SDave May }
1163cb1d1399SDave May 
116474d0cae8SMatthew G. Knepley /*@
1165d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
1166d3a51819SDave May 
1167d3a51819SDave May    Not collective
1168d3a51819SDave May 
1169d3a51819SDave May    Input parameter:
1170d3a51819SDave May .  dm - a DMSwarm
1171d3a51819SDave May 
1172d3a51819SDave May    Level: beginner
1173d3a51819SDave May 
1174db781477SPatrick Sanan .seealso: `DMSwarmRemovePointAtIndex()`
1175d3a51819SDave May @*/
1176d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePoint(DM dm)
1177d71ae5a4SJacob Faibussowitsch {
1178cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1179cb1d1399SDave May 
1180521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
11829566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePoint(swarm->db));
11839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
1184cb1d1399SDave May   PetscFunctionReturn(0);
1185cb1d1399SDave May }
1186cb1d1399SDave May 
118774d0cae8SMatthew G. Knepley /*@
1188d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
1189d3a51819SDave May 
1190d3a51819SDave May    Not collective
1191d3a51819SDave May 
1192d3a51819SDave May    Input parameters:
119362741f57SDave May +  dm - a DMSwarm
119462741f57SDave May -  idx - index of point to remove
1195d3a51819SDave May 
1196d3a51819SDave May    Level: beginner
1197d3a51819SDave May 
1198db781477SPatrick Sanan .seealso: `DMSwarmRemovePoint()`
1199d3a51819SDave May @*/
1200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx)
1201d71ae5a4SJacob Faibussowitsch {
1202cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1203cb1d1399SDave May 
1204521f74f9SMatthew G. Knepley   PetscFunctionBegin;
12059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
12069566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx));
12079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
1208cb1d1399SDave May   PetscFunctionReturn(0);
1209cb1d1399SDave May }
1210b62e03f8SDave May 
121174d0cae8SMatthew G. Knepley /*@
1212ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
1213ba4fc9c6SDave May 
1214ba4fc9c6SDave May    Not collective
1215ba4fc9c6SDave May 
1216ba4fc9c6SDave May    Input parameters:
1217ba4fc9c6SDave May +  dm - a DMSwarm
1218ba4fc9c6SDave May .  pi - the index of the point to copy
1219ba4fc9c6SDave May -  pj - the point index where the copy should be located
1220ba4fc9c6SDave May 
1221ba4fc9c6SDave May  Level: beginner
1222ba4fc9c6SDave May 
1223db781477SPatrick Sanan .seealso: `DMSwarmRemovePoint()`
1224ba4fc9c6SDave May @*/
1225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj)
1226d71ae5a4SJacob Faibussowitsch {
1227ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1228ba4fc9c6SDave May 
1229ba4fc9c6SDave May   PetscFunctionBegin;
12309566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
12319566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj));
1232ba4fc9c6SDave May   PetscFunctionReturn(0);
1233ba4fc9c6SDave May }
1234ba4fc9c6SDave May 
1235d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points)
1236d71ae5a4SJacob Faibussowitsch {
1237521f74f9SMatthew G. Knepley   PetscFunctionBegin;
12389566063dSJacob Faibussowitsch   PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points));
12393454631fSDave May   PetscFunctionReturn(0);
12403454631fSDave May }
12413454631fSDave May 
124274d0cae8SMatthew G. Knepley /*@
1243d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
1244d3a51819SDave May 
1245d083f849SBarry Smith    Collective on dm
1246d3a51819SDave May 
1247d3a51819SDave May    Input parameters:
124862741f57SDave May +  dm - the DMSwarm
124962741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1250d3a51819SDave May 
1251d3a51819SDave May    Notes:
1252a5b23f4aSJose E. Roman    The DM will be modified to accommodate received points.
12538b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
12548b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
1255d3a51819SDave May 
1256d3a51819SDave May    Level: advanced
1257d3a51819SDave May 
1258db781477SPatrick Sanan .seealso: `DMSwarmSetMigrateType()`
1259d3a51819SDave May @*/
1260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points)
1261d71ae5a4SJacob Faibussowitsch {
1262f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1263f0cdbbbaSDave May 
1264521f74f9SMatthew G. Knepley   PetscFunctionBegin;
12659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0));
1266f0cdbbbaSDave May   switch (swarm->migrate_type) {
1267d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_BASIC:
1268d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points));
1269d71ae5a4SJacob Faibussowitsch     break;
1270d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLNSCATTER:
1271d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points));
1272d71ae5a4SJacob Faibussowitsch     break;
1273d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLEXACT:
1274d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1275d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_USER:
1276d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented");
1277d71ae5a4SJacob Faibussowitsch   default:
1278d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown");
1279f0cdbbbaSDave May   }
12809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0));
12819566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(dm));
12823454631fSDave May   PetscFunctionReturn(0);
12833454631fSDave May }
12843454631fSDave May 
1285f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize);
1286f0cdbbbaSDave May 
1287d3a51819SDave May /*
1288d3a51819SDave May  DMSwarmCollectViewCreate
1289d3a51819SDave May 
1290d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1291d3a51819SDave May 
1292d3a51819SDave May  Notes:
12938b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1294d3a51819SDave May  they have finished computations associated with the collected points
1295d3a51819SDave May */
1296d3a51819SDave May 
129774d0cae8SMatthew G. Knepley /*@
1298d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
12995627991aSBarry Smith                               in neighbour ranks into the DMSwarm
1300d3a51819SDave May 
1301d083f849SBarry Smith    Collective on dm
1302d3a51819SDave May 
1303d3a51819SDave May    Input parameter:
1304d3a51819SDave May .  dm - the DMSwarm
1305d3a51819SDave May 
1306d3a51819SDave May    Notes:
1307d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1308d3a51819SDave May    they have finished computations associated with the collected points
13098b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1310d3a51819SDave May 
1311d3a51819SDave May    Level: advanced
1312d3a51819SDave May 
1313db781477SPatrick Sanan .seealso: `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()`
1314d3a51819SDave May @*/
1315d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewCreate(DM dm)
1316d71ae5a4SJacob Faibussowitsch {
13172712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
13182712d1f2SDave May   PetscInt  ng;
13192712d1f2SDave May 
1320521f74f9SMatthew G. Knepley   PetscFunctionBegin;
132128b400f6SJacob Faibussowitsch   PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active");
13229566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &ng));
1323480eef7bSDave May   switch (swarm->collect_type) {
1324d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_BASIC:
1325d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng));
1326d71ae5a4SJacob Faibussowitsch     break;
1327d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1328d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1329d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_GENERAL:
1330d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented");
1331d71ae5a4SJacob Faibussowitsch   default:
1332d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown");
1333480eef7bSDave May   }
1334480eef7bSDave May   swarm->collect_view_active       = PETSC_TRUE;
1335480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
13362712d1f2SDave May   PetscFunctionReturn(0);
13372712d1f2SDave May }
13382712d1f2SDave May 
133974d0cae8SMatthew G. Knepley /*@
1340d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1341d3a51819SDave May 
1342d083f849SBarry Smith    Collective on dm
1343d3a51819SDave May 
1344d3a51819SDave May    Input parameters:
1345d3a51819SDave May .  dm - the DMSwarm
1346d3a51819SDave May 
1347d3a51819SDave May    Notes:
1348d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1349d3a51819SDave May 
1350d3a51819SDave May    Level: advanced
1351d3a51819SDave May 
1352db781477SPatrick Sanan .seealso: `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()`
1353d3a51819SDave May @*/
1354d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
1355d71ae5a4SJacob Faibussowitsch {
13562712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
13572712d1f2SDave May 
1358521f74f9SMatthew G. Knepley   PetscFunctionBegin;
135928b400f6SJacob Faibussowitsch   PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active");
13609566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1));
1361480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
13622712d1f2SDave May   PetscFunctionReturn(0);
13632712d1f2SDave May }
13643454631fSDave May 
1365d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetUpPIC(DM dm)
1366d71ae5a4SJacob Faibussowitsch {
1367f0cdbbbaSDave May   PetscInt dim;
1368f0cdbbbaSDave May 
1369521f74f9SMatthew G. Knepley   PetscFunctionBegin;
13709566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetNumSpecies(dm, 1));
13719566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
137263a3b9bcSJacob Faibussowitsch   PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
137363a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
13749566063dSJacob Faibussowitsch   PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_coor, dim, PETSC_DOUBLE));
13759566063dSJacob Faibussowitsch   PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_cellid, 1, PETSC_INT));
1376f0cdbbbaSDave May   PetscFunctionReturn(0);
1377f0cdbbbaSDave May }
1378f0cdbbbaSDave May 
137974d0cae8SMatthew G. Knepley /*@
138031403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
138131403186SMatthew G. Knepley 
138231403186SMatthew G. Knepley   Collective on dm
138331403186SMatthew G. Knepley 
138431403186SMatthew G. Knepley   Input parameters:
138531403186SMatthew G. Knepley + dm  - the DMSwarm
138631403186SMatthew G. Knepley - Npc - The number of particles per cell in the cell DM
138731403186SMatthew G. Knepley 
138831403186SMatthew G. Knepley   Notes:
138931403186SMatthew G. Knepley   The user must use DMSwarmSetCellDM() to set the cell DM first. The particles are placed randomly inside each cell. If only
139031403186SMatthew G. Knepley   one particle is in each cell, it is placed at the centroid.
139131403186SMatthew G. Knepley 
139231403186SMatthew G. Knepley   Level: intermediate
139331403186SMatthew G. Knepley 
1394db781477SPatrick Sanan .seealso: `DMSwarmSetCellDM()`
139531403186SMatthew G. Knepley @*/
1396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
1397d71ae5a4SJacob Faibussowitsch {
139831403186SMatthew G. Knepley   DM             cdm;
139931403186SMatthew G. Knepley   PetscRandom    rnd;
140031403186SMatthew G. Knepley   DMPolytopeType ct;
140131403186SMatthew G. Knepley   PetscBool      simplex;
140231403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
140331403186SMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p;
140431403186SMatthew G. Knepley 
140531403186SMatthew G. Knepley   PetscFunctionBeginUser;
14069566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd));
14079566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0));
14089566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetType(rnd, PETSCRAND48));
140931403186SMatthew G. Knepley 
14109566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
14119566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(cdm, &dim));
14129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd));
14139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(cdm, cStart, &ct));
141431403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
141531403186SMatthew G. Knepley 
14169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ));
141731403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
14189566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
141931403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
142031403186SMatthew G. Knepley     if (Npc == 1) {
14219566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL));
142231403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d];
142331403186SMatthew G. Knepley     } else {
14249566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */
142531403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
142631403186SMatthew G. Knepley         const PetscInt n   = c * Npc + p;
142731403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
142831403186SMatthew G. Knepley 
142931403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
14309566063dSJacob Faibussowitsch           PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d]));
143131403186SMatthew G. Knepley           sum += refcoords[d];
143231403186SMatthew G. Knepley         }
14339371c9d4SSatish Balay         if (simplex && sum > 0.0)
14349371c9d4SSatish Balay           for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum;
143531403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]);
143631403186SMatthew G. Knepley       }
143731403186SMatthew G. Knepley     }
143831403186SMatthew G. Knepley   }
14399566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords));
14409566063dSJacob Faibussowitsch   PetscCall(PetscFree5(centroid, xi0, v0, J, invJ));
14419566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rnd));
144231403186SMatthew G. Knepley   PetscFunctionReturn(0);
144331403186SMatthew G. Knepley }
144431403186SMatthew G. Knepley 
144531403186SMatthew G. Knepley /*@
1446d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1447d3a51819SDave May 
1448d083f849SBarry Smith    Collective on dm
1449d3a51819SDave May 
1450d3a51819SDave May    Input parameters:
145162741f57SDave May +  dm - the DMSwarm
145262741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1453d3a51819SDave May 
1454d3a51819SDave May    Level: advanced
1455d3a51819SDave May 
1456db781477SPatrick Sanan .seealso: `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC`
1457d3a51819SDave May @*/
1458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetType(DM dm, DMSwarmType stype)
1459d71ae5a4SJacob Faibussowitsch {
1460f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1461f0cdbbbaSDave May 
1462521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1463f0cdbbbaSDave May   swarm->swarm_type = stype;
146448a46eb9SPierre Jolivet   if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(dm));
1465f0cdbbbaSDave May   PetscFunctionReturn(0);
1466f0cdbbbaSDave May }
1467f0cdbbbaSDave May 
1468d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetup_Swarm(DM dm)
1469d71ae5a4SJacob Faibussowitsch {
14703454631fSDave May   DM_Swarm   *swarm = (DM_Swarm *)dm->data;
14713454631fSDave May   PetscMPIInt rank;
14723454631fSDave May   PetscInt    p, npoints, *rankval;
14733454631fSDave May 
1474521f74f9SMatthew G. Knepley   PetscFunctionBegin;
14753454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
14763454631fSDave May   swarm->issetup = PETSC_TRUE;
14773454631fSDave May 
1478f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1479f0cdbbbaSDave May     /* check dmcell exists */
148028b400f6SJacob Faibussowitsch     PetscCheck(swarm->dmcell, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires you call DMSwarmSetCellDM");
1481f0cdbbbaSDave May 
1482f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1483f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
14849566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n"));
1485f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1486f0cdbbbaSDave May     } else {
1487f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1488f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
14899566063dSJacob Faibussowitsch         PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n"));
1490f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1491f0cdbbbaSDave May 
1492f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
14939566063dSJacob Faibussowitsch         PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n"));
1494f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1495f0cdbbbaSDave May 
1496f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1497f0cdbbbaSDave May     }
1498f0cdbbbaSDave May   }
1499f0cdbbbaSDave May 
15009566063dSJacob Faibussowitsch   PetscCall(DMSwarmFinalizeFieldRegister(dm));
1501f0cdbbbaSDave May 
15023454631fSDave May   /* check some fields were registered */
150308401ef6SPierre Jolivet   PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()");
15043454631fSDave May 
15053454631fSDave May   /* check local sizes were set */
150608401ef6SPierre Jolivet   PetscCheck(swarm->db->L != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Local sizes must be set via DMSwarmSetLocalSizes()");
15073454631fSDave May 
15083454631fSDave May   /* initialize values in pid and rank placeholders */
15093454631fSDave May   /* TODO: [pid - use MPI_Scan] */
15109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15119566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
15129566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
1513ad540459SPierre Jolivet   for (p = 0; p < npoints; p++) rankval[p] = (PetscInt)rank;
15149566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
15153454631fSDave May   PetscFunctionReturn(0);
15163454631fSDave May }
15173454631fSDave May 
1518dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1519dc5f5ce9SDave May 
1520d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Swarm(DM dm)
1521d71ae5a4SJacob Faibussowitsch {
152257795646SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
152357795646SDave May 
152457795646SDave May   PetscFunctionBegin;
1525d0c080abSJoseph Pusztay   if (--swarm->refct > 0) PetscFunctionReturn(0);
15269566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&swarm->db));
152748a46eb9SPierre Jolivet   if (swarm->sort_context) PetscCall(DMSwarmSortDestroy(&swarm->sort_context));
15289566063dSJacob Faibussowitsch   PetscCall(PetscFree(swarm));
152957795646SDave May   PetscFunctionReturn(0);
153057795646SDave May }
153157795646SDave May 
1532d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1533d71ae5a4SJacob Faibussowitsch {
1534a9ee3421SMatthew G. Knepley   DM         cdm;
1535a9ee3421SMatthew G. Knepley   PetscDraw  draw;
153631403186SMatthew G. Knepley   PetscReal *coords, oldPause, radius = 0.01;
1537a9ee3421SMatthew G. Knepley   PetscInt   Np, p, bs;
1538a9ee3421SMatthew G. Knepley 
1539a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
15409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL));
15419566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
15429566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
15439566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetPause(draw, &oldPause));
15449566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, 0.0));
15459566063dSJacob Faibussowitsch   PetscCall(DMView(cdm, viewer));
15469566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, oldPause));
1547a9ee3421SMatthew G. Knepley 
15489566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &Np));
15499566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **)&coords));
1550a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1551a9ee3421SMatthew G. Knepley     const PetscInt i = p * bs;
1552a9ee3421SMatthew G. Knepley 
15539566063dSJacob Faibussowitsch     PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE));
1554a9ee3421SMatthew G. Knepley   }
15559566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **)&coords));
15569566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
15579566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
15589566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1559a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1560a9ee3421SMatthew G. Knepley }
1561a9ee3421SMatthew G. Knepley 
1562d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer)
1563d71ae5a4SJacob Faibussowitsch {
15646a5217c0SMatthew G. Knepley   PetscViewerFormat format;
15656a5217c0SMatthew G. Knepley   PetscInt         *sizes;
15666a5217c0SMatthew G. Knepley   PetscInt          dim, Np, maxSize = 17;
15676a5217c0SMatthew G. Knepley   MPI_Comm          comm;
15686a5217c0SMatthew G. Knepley   PetscMPIInt       rank, size, p;
15696a5217c0SMatthew G. Knepley   const char       *name;
15706a5217c0SMatthew G. Knepley 
15716a5217c0SMatthew G. Knepley   PetscFunctionBegin;
15726a5217c0SMatthew G. Knepley   PetscCall(PetscViewerGetFormat(viewer, &format));
15736a5217c0SMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
15746a5217c0SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dm, &Np));
15756a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
15766a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
15776a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
15786a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
157963a3b9bcSJacob Faibussowitsch   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
158063a3b9bcSJacob Faibussowitsch   else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
15816a5217c0SMatthew G. Knepley   if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes));
15826a5217c0SMatthew G. Knepley   else PetscCall(PetscCalloc1(3, &sizes));
15836a5217c0SMatthew G. Knepley   if (size < maxSize) {
15846a5217c0SMatthew G. Knepley     PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
15856a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of particles per rank:"));
15866a5217c0SMatthew G. Knepley     for (p = 0; p < size; ++p) {
15876a5217c0SMatthew G. Knepley       if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]));
15886a5217c0SMatthew G. Knepley     }
15896a5217c0SMatthew G. Knepley   } else {
15906a5217c0SMatthew G. Knepley     PetscInt locMinMax[2] = {Np, Np};
15916a5217c0SMatthew G. Knepley 
15926a5217c0SMatthew G. Knepley     PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
15936a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
15946a5217c0SMatthew G. Knepley   }
15956a5217c0SMatthew G. Knepley   PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
15966a5217c0SMatthew G. Knepley   PetscCall(PetscFree(sizes));
15976a5217c0SMatthew G. Knepley   if (format == PETSC_VIEWER_ASCII_INFO) {
15986a5217c0SMatthew G. Knepley     PetscInt *cell;
15996a5217c0SMatthew G. Knepley 
16006a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells containing each particle:\n"));
16016a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
16026a5217c0SMatthew G. Knepley     PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell));
160363a3b9bcSJacob Faibussowitsch     for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  p%d: %" PetscInt_FMT "\n", p, cell[p]));
16046a5217c0SMatthew G. Knepley     PetscCall(PetscViewerFlush(viewer));
16056a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
16066a5217c0SMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell));
16076a5217c0SMatthew G. Knepley   }
16086a5217c0SMatthew G. Knepley   PetscFunctionReturn(0);
16096a5217c0SMatthew G. Knepley }
16106a5217c0SMatthew G. Knepley 
1611d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
1612d71ae5a4SJacob Faibussowitsch {
16135f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
16145627991aSBarry Smith   PetscBool iascii, ibinary, isvtk, isdraw;
16155627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
16165627991aSBarry Smith   PetscBool ishdf5;
16175627991aSBarry Smith #endif
16185f50eb2eSDave May 
16195f50eb2eSDave May   PetscFunctionBegin;
16205f50eb2eSDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16215f50eb2eSDave May   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
16229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
16239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
16249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
16255627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
16269566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
16275627991aSBarry Smith #endif
16289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
16295f50eb2eSDave May   if (iascii) {
16306a5217c0SMatthew G. Knepley     PetscViewerFormat format;
16316a5217c0SMatthew G. Knepley 
16326a5217c0SMatthew G. Knepley     PetscCall(PetscViewerGetFormat(viewer, &format));
16336a5217c0SMatthew G. Knepley     switch (format) {
1634d71ae5a4SJacob Faibussowitsch     case PETSC_VIEWER_ASCII_INFO_DETAIL:
1635d71ae5a4SJacob Faibussowitsch       PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT));
1636d71ae5a4SJacob Faibussowitsch       break;
1637d71ae5a4SJacob Faibussowitsch     default:
1638d71ae5a4SJacob Faibussowitsch       PetscCall(DMView_Swarm_Ascii(dm, viewer));
16396a5217c0SMatthew G. Knepley     }
1640f7d195e4SLawrence Mitchell   } else {
16415f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
164248a46eb9SPierre Jolivet     if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer));
16435f50eb2eSDave May #endif
164448a46eb9SPierre Jolivet     if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer));
1645f7d195e4SLawrence Mitchell   }
16465f50eb2eSDave May   PetscFunctionReturn(0);
16475f50eb2eSDave May }
16485f50eb2eSDave May 
1649d0c080abSJoseph Pusztay /*@C
1650d0c080abSJoseph Pusztay    DMSwarmGetCellSwarm - Extracts a single cell from the DMSwarm object, returns it as a single cell DMSwarm.
1651d0c080abSJoseph 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.
1652d0c080abSJoseph Pusztay 
1653d0c080abSJoseph Pusztay    Important: Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
1654d0c080abSJoseph Pusztay 
1655d0c080abSJoseph Pusztay    Noncollective
1656d0c080abSJoseph Pusztay 
1657d0c080abSJoseph Pusztay    Input parameters:
1658d0c080abSJoseph Pusztay +  sw - the DMSwarm
16595627991aSBarry Smith .  cellID - the integer id of the cell to be extracted and filtered
16605627991aSBarry Smith -  cellswarm - The DMSwarm to receive the cell
1661d0c080abSJoseph Pusztay 
1662d0c080abSJoseph Pusztay    Level: beginner
1663d0c080abSJoseph Pusztay 
16645627991aSBarry Smith    Notes:
16655627991aSBarry Smith       This presently only supports DMSWARM_PIC type
16665627991aSBarry Smith 
16675627991aSBarry Smith       Should be restored with DMSwarmRestoreCellSwarm()
1668d0c080abSJoseph Pusztay 
1669db781477SPatrick Sanan .seealso: `DMSwarmRestoreCellSwarm()`
1670d0c080abSJoseph Pusztay @*/
1671d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1672d71ae5a4SJacob Faibussowitsch {
1673d0c080abSJoseph Pusztay   DM_Swarm *original = (DM_Swarm *)sw->data;
1674d0c080abSJoseph Pusztay   DMLabel   label;
1675d0c080abSJoseph Pusztay   DM        dmc, subdmc;
1676d0c080abSJoseph Pusztay   PetscInt *pids, particles, dim;
1677d0c080abSJoseph Pusztay 
1678d0c080abSJoseph Pusztay   PetscFunctionBegin;
1679d0c080abSJoseph Pusztay   /* Configure new swarm */
16809566063dSJacob Faibussowitsch   PetscCall(DMSetType(cellswarm, DMSWARM));
16819566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(sw, &dim));
16829566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(cellswarm, dim));
16839566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC));
1684d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
16859566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db));
16869566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
16879566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles));
16889566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
16899566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db));
16909566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
16919566063dSJacob Faibussowitsch   PetscCall(PetscFree(pids));
16929566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(sw, &dmc));
16939566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label));
16949566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(dmc, label));
16959566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cellID, 1));
16969566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dmc, label, 1, &subdmc));
16979566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetCellDM(cellswarm, subdmc));
16989566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
1699d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1700d0c080abSJoseph Pusztay }
1701d0c080abSJoseph Pusztay 
1702d0c080abSJoseph Pusztay /*@C
17035627991aSBarry Smith    DMSwarmRestoreCellSwarm - Restores a DMSwarm object obtained with DMSwarmGetCellSwarm(). All fields are copied back into the parent swarm.
1704d0c080abSJoseph Pusztay 
1705d0c080abSJoseph Pusztay    Noncollective
1706d0c080abSJoseph Pusztay 
1707d0c080abSJoseph Pusztay    Input parameters:
1708d0c080abSJoseph Pusztay +  sw - the parent DMSwarm
1709d0c080abSJoseph Pusztay .  cellID - the integer id of the cell to be copied back into the parent swarm
1710d0c080abSJoseph Pusztay -  cellswarm - the cell swarm object
1711d0c080abSJoseph Pusztay 
1712d0c080abSJoseph Pusztay    Level: beginner
1713d0c080abSJoseph Pusztay 
17145627991aSBarry Smith    Note:
17155627991aSBarry Smith     This only supports DMSWARM_PIC types of DMSwarms
1716d0c080abSJoseph Pusztay 
1717db781477SPatrick Sanan .seealso: `DMSwarmGetCellSwarm()`
1718d0c080abSJoseph Pusztay @*/
1719d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1720d71ae5a4SJacob Faibussowitsch {
1721d0c080abSJoseph Pusztay   DM        dmc;
1722d0c080abSJoseph Pusztay   PetscInt *pids, particles, p;
1723d0c080abSJoseph Pusztay 
1724d0c080abSJoseph Pusztay   PetscFunctionBegin;
17259566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
17269566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
17279566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
1728d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
172948a46eb9SPierre Jolivet   for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p]));
1730d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
17319566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(cellswarm, &dmc));
17329566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
17339566063dSJacob Faibussowitsch   PetscCall(PetscFree(pids));
1734d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1735d0c080abSJoseph Pusztay }
1736d0c080abSJoseph Pusztay 
1737d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
1738d0c080abSJoseph Pusztay 
1739d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Swarm(DM sw)
1740d71ae5a4SJacob Faibussowitsch {
1741d0c080abSJoseph Pusztay   PetscFunctionBegin;
1742d0c080abSJoseph Pusztay   sw->dim                           = 0;
1743d0c080abSJoseph Pusztay   sw->ops->view                     = DMView_Swarm;
1744d0c080abSJoseph Pusztay   sw->ops->load                     = NULL;
1745d0c080abSJoseph Pusztay   sw->ops->setfromoptions           = NULL;
1746d0c080abSJoseph Pusztay   sw->ops->clone                    = DMClone_Swarm;
1747d0c080abSJoseph Pusztay   sw->ops->setup                    = DMSetup_Swarm;
1748d0c080abSJoseph Pusztay   sw->ops->createlocalsection       = NULL;
1749d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints = NULL;
1750d0c080abSJoseph Pusztay   sw->ops->createglobalvector       = DMCreateGlobalVector_Swarm;
1751d0c080abSJoseph Pusztay   sw->ops->createlocalvector        = DMCreateLocalVector_Swarm;
1752d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping  = NULL;
1753d0c080abSJoseph Pusztay   sw->ops->createfieldis            = NULL;
1754d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm       = NULL;
1755d0c080abSJoseph Pusztay   sw->ops->getcoloring              = NULL;
1756d0c080abSJoseph Pusztay   sw->ops->creatematrix             = DMCreateMatrix_Swarm;
1757d0c080abSJoseph Pusztay   sw->ops->createinterpolation      = NULL;
1758d0c080abSJoseph Pusztay   sw->ops->createinjection          = NULL;
1759d0c080abSJoseph Pusztay   sw->ops->createmassmatrix         = DMCreateMassMatrix_Swarm;
1760d0c080abSJoseph Pusztay   sw->ops->refine                   = NULL;
1761d0c080abSJoseph Pusztay   sw->ops->coarsen                  = NULL;
1762d0c080abSJoseph Pusztay   sw->ops->refinehierarchy          = NULL;
1763d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy         = NULL;
1764d0c080abSJoseph Pusztay   sw->ops->globaltolocalbegin       = NULL;
1765d0c080abSJoseph Pusztay   sw->ops->globaltolocalend         = NULL;
1766d0c080abSJoseph Pusztay   sw->ops->localtoglobalbegin       = NULL;
1767d0c080abSJoseph Pusztay   sw->ops->localtoglobalend         = NULL;
1768d0c080abSJoseph Pusztay   sw->ops->destroy                  = DMDestroy_Swarm;
1769d0c080abSJoseph Pusztay   sw->ops->createsubdm              = NULL;
1770d0c080abSJoseph Pusztay   sw->ops->getdimpoints             = NULL;
1771d0c080abSJoseph Pusztay   sw->ops->locatepoints             = NULL;
1772d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1773d0c080abSJoseph Pusztay }
1774d0c080abSJoseph Pusztay 
1775d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm)
1776d71ae5a4SJacob Faibussowitsch {
1777d0c080abSJoseph Pusztay   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1778d0c080abSJoseph Pusztay 
1779d0c080abSJoseph Pusztay   PetscFunctionBegin;
1780d0c080abSJoseph Pusztay   swarm->refct++;
1781d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
17829566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM));
17839566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(*newdm));
17842e56dffeSJoe Pusztay   (*newdm)->dim = dm->dim;
1785d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1786d0c080abSJoseph Pusztay }
1787d0c080abSJoseph Pusztay 
1788d3a51819SDave May /*MC
1789d3a51819SDave May 
1790d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
179162741f57SDave May  This implementation was designed for particle methods in which the underlying
1792d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1793d3a51819SDave May 
179462741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
179562741f57SDave May  To register a field, the user must provide;
179662741f57SDave May  (a) a unique name;
179762741f57SDave May  (b) the data type (or size in bytes);
179862741f57SDave May  (c) the block size of the data.
1799d3a51819SDave May 
1800d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1801c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1802d3a51819SDave May 
180362741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
180462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
180562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
180662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
180762741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
180862741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1809d3a51819SDave May 
1810d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
181162741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1812d3a51819SDave May 
1813d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
18145627991aSBarry Smith  between ranks.
1815d3a51819SDave May 
1816d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1817d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
181862741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1819d3a51819SDave May  fields should be used to define a Vec object via
1820d3a51819SDave May    DMSwarmVectorDefineField()
1821c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1822c215a47eSMatthew Knepley  compatible with different fields to be created.
1823d3a51819SDave May 
182462741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1825d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1826d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1827d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1828d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1829cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1830cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1831d3a51819SDave May 
183262741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
183362741f57SDave May  Please refer to the man page for DMSwarmSetType().
183462741f57SDave May 
1835d3a51819SDave May  Level: beginner
1836d3a51819SDave May 
1837db781477SPatrick Sanan .seealso: `DMType`, `DMCreate()`, `DMSetType()`
1838d3a51819SDave May M*/
1839d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
1840d71ae5a4SJacob Faibussowitsch {
184157795646SDave May   DM_Swarm *swarm;
184257795646SDave May 
184357795646SDave May   PetscFunctionBegin;
184457795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18454dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&swarm));
1846f0cdbbbaSDave May   dm->data = swarm;
18479566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreate(&swarm->db));
18489566063dSJacob Faibussowitsch   PetscCall(DMSwarmInitializeFieldRegister(dm));
1849d0c080abSJoseph Pusztay   swarm->refct                          = 1;
1850b5bcf523SDave May   swarm->vec_field_set                  = PETSC_FALSE;
18513454631fSDave May   swarm->issetup                        = PETSC_FALSE;
1852480eef7bSDave May   swarm->swarm_type                     = DMSWARM_BASIC;
1853480eef7bSDave May   swarm->migrate_type                   = DMSWARM_MIGRATE_BASIC;
1854480eef7bSDave May   swarm->collect_type                   = DMSWARM_COLLECT_BASIC;
185540c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1856f0cdbbbaSDave May   swarm->dmcell                         = NULL;
1857f0cdbbbaSDave May   swarm->collect_view_active            = PETSC_FALSE;
1858f0cdbbbaSDave May   swarm->collect_view_reset_nlocal      = -1;
18599566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(dm));
18602e956fe4SStefano Zampini   if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId));
186157795646SDave May   PetscFunctionReturn(0);
186257795646SDave May }
1863