xref: /petsc/src/dm/impls/swarm/swarm.c (revision 19307e5cf369b208f3c5d721c42c941e418b5101)
1*19307e5cSMatthew G. Knepley #include "petscdm.h"
2*19307e5cSMatthew G. Knepley #include "petscdmswarm.h"
3*19307e5cSMatthew G. Knepley #include "petscstring.h"
4d52c2f21SMatthew G. Knepley #include "petscsys.h"
557795646SDave May #define PETSCDM_DLL
657795646SDave May #include <petsc/private/dmswarmimpl.h> /*I   "petscdmswarm.h"   I*/
7e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
80643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>
95917a6f0SStefano Zampini #include <petscviewer.h>
105917a6f0SStefano Zampini #include <petscdraw.h>
1183c47955SMatthew G. Knepley #include <petscdmplex.h>
124cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h>
13279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
14d0c080abSJoseph Pusztay #include <petscdmlabel.h>
15d0c080abSJoseph Pusztay #include <petscsection.h>
1657795646SDave May 
17f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
18ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
19ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
20ed923d71SDave May 
21ea78f98cSLisandro Dalcin const char *DMSwarmTypeNames[]          = {"basic", "pic", NULL};
22ea78f98cSLisandro Dalcin const char *DMSwarmMigrateTypeNames[]   = {"basic", "dmcellnscatter", "dmcellexact", "user", NULL};
23ea78f98cSLisandro Dalcin const char *DMSwarmCollectTypeNames[]   = {"basic", "boundingbox", "general", "user", NULL};
24ea78f98cSLisandro Dalcin const char *DMSwarmPICLayoutTypeNames[] = {"regular", "gauss", "subdivision", NULL};
25f0cdbbbaSDave May 
26f0cdbbbaSDave May const char DMSwarmField_pid[]     = "DMSwarm_pid";
27f0cdbbbaSDave May const char DMSwarmField_rank[]    = "DMSwarm_rank";
28f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
29f0cdbbbaSDave May 
302e956fe4SStefano Zampini PetscInt SwarmDataFieldId = -1;
312e956fe4SStefano Zampini 
3274d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
3374d0cae8SMatthew G. Knepley   #include <petscviewerhdf5.h>
3474d0cae8SMatthew G. Knepley 
3566976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer)
36d71ae5a4SJacob Faibussowitsch {
3774d0cae8SMatthew G. Knepley   DM        dm;
3874d0cae8SMatthew G. Knepley   PetscReal seqval;
3974d0cae8SMatthew G. Knepley   PetscInt  seqnum, bs;
40eb0c6899SMatthew G. Knepley   PetscBool isseq, ists;
4174d0cae8SMatthew G. Knepley 
4274d0cae8SMatthew G. Knepley   PetscFunctionBegin;
439566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
449566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(v, &bs));
459566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields"));
469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
479566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval));
48eb0c6899SMatthew G. Knepley   PetscCall(PetscViewerHDF5IsTimestepping(viewer, &ists));
49eb0c6899SMatthew G. Knepley   if (ists) PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
509566063dSJacob Faibussowitsch   /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */
519566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
529566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs));
539566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5574d0cae8SMatthew G. Knepley }
5674d0cae8SMatthew G. Knepley 
5766976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer)
58d71ae5a4SJacob Faibussowitsch {
59*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
6074d0cae8SMatthew G. Knepley   Vec           coordinates;
61*19307e5cSMatthew G. Knepley   PetscInt      Np, Nfc;
6274d0cae8SMatthew G. Knepley   PetscBool     isseq;
63*19307e5cSMatthew G. Knepley   const char  **coordFields;
6474d0cae8SMatthew G. Knepley 
6574d0cae8SMatthew G. Knepley   PetscFunctionBegin;
66*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
67*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
68*19307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
699566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetSize(dm, &Np));
70*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateGlobalVectorFromField(dm, coordFields[0], &coordinates));
719566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
729566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles"));
739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq));
749566063dSJacob Faibussowitsch   PetscCall(VecViewNative(coordinates, viewer));
759566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np));
769566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
77*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, coordFields[0], &coordinates));
783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7974d0cae8SMatthew G. Knepley }
8074d0cae8SMatthew G. Knepley #endif
8174d0cae8SMatthew G. Knepley 
8266976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer)
83d71ae5a4SJacob Faibussowitsch {
8474d0cae8SMatthew G. Knepley   DM dm;
85f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
8674d0cae8SMatthew G. Knepley   PetscBool ishdf5;
87f9558f5cSBarry Smith #endif
8874d0cae8SMatthew G. Knepley 
8974d0cae8SMatthew G. Knepley   PetscFunctionBegin;
909566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
9128b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
92f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
9474d0cae8SMatthew G. Knepley   if (ishdf5) {
959566063dSJacob Faibussowitsch     PetscCall(VecView_Swarm_HDF5_Internal(v, viewer));
963ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9774d0cae8SMatthew G. Knepley   }
98f9558f5cSBarry Smith #endif
999566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
1003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10174d0cae8SMatthew G. Knepley }
10274d0cae8SMatthew G. Knepley 
103d52c2f21SMatthew G. Knepley /*@C
104d52c2f21SMatthew G. Knepley   DMSwarmVectorGetField - Gets the fields from which to define a `Vec` object
1050bf7c1c5SMatthew G. Knepley   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
1060bf7c1c5SMatthew G. Knepley 
1070bf7c1c5SMatthew G. Knepley   Not collective
1080bf7c1c5SMatthew G. Knepley 
1090bf7c1c5SMatthew G. Knepley   Input Parameter:
110*19307e5cSMatthew G. Knepley . sw - a `DMSWARM`
1110bf7c1c5SMatthew G. Knepley 
112d52c2f21SMatthew G. Knepley   Output Parameters:
113d52c2f21SMatthew G. Knepley + Nf         - the number of fields
114d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field, or NULL if it has not been set
1150bf7c1c5SMatthew G. Knepley 
1160bf7c1c5SMatthew G. Knepley   Level: beginner
1170bf7c1c5SMatthew G. Knepley 
118d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
1190bf7c1c5SMatthew G. Knepley @*/
120*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorGetField(DM sw, PetscInt *Nf, const char **fieldnames[])
1210bf7c1c5SMatthew G. Knepley {
122*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
123*19307e5cSMatthew G. Knepley 
1240bf7c1c5SMatthew G. Knepley   PetscFunctionBegin;
125*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM);
126*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
127*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetFields(celldm, Nf, fieldnames));
1280bf7c1c5SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1290bf7c1c5SMatthew G. Knepley }
1300bf7c1c5SMatthew G. Knepley 
131cc4c1da9SBarry Smith /*@
13220f4b53cSBarry Smith   DMSwarmVectorDefineField - Sets the field from which to define a `Vec` object
13320f4b53cSBarry Smith   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
13457795646SDave May 
13520f4b53cSBarry Smith   Collective
13657795646SDave May 
13760225df5SJacob Faibussowitsch   Input Parameters:
13820f4b53cSBarry Smith + dm        - a `DMSWARM`
139d52c2f21SMatthew G. Knepley - fieldname - the textual name given to each registered field
14057795646SDave May 
141d3a51819SDave May   Level: beginner
14257795646SDave May 
143d3a51819SDave May   Notes:
14420f4b53cSBarry Smith   The field with name `fieldname` must be defined as having a data type of `PetscScalar`.
145e7af74c8SDave May 
14620f4b53cSBarry Smith   This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`.
14720f4b53cSBarry Smith   Multiple calls to `DMSwarmVectorDefineField()` are permitted.
148e7af74c8SDave May 
149d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineFields()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
150d3a51819SDave May @*/
151d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[])
152d71ae5a4SJacob Faibussowitsch {
153d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
154d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmVectorDefineFields(dm, 1, &fieldname));
155d52c2f21SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
156d52c2f21SMatthew G. Knepley }
157d52c2f21SMatthew G. Knepley 
158d52c2f21SMatthew G. Knepley /*@C
159d52c2f21SMatthew G. Knepley   DMSwarmVectorDefineFields - Sets the fields from which to define a `Vec` object
160d52c2f21SMatthew G. Knepley   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
161d52c2f21SMatthew G. Knepley 
162d52c2f21SMatthew G. Knepley   Collective, No Fortran support
163d52c2f21SMatthew G. Knepley 
164d52c2f21SMatthew G. Knepley   Input Parameters:
165*19307e5cSMatthew G. Knepley + sw         - a `DMSWARM`
166d52c2f21SMatthew G. Knepley . Nf         - the number of fields
167d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field
168d52c2f21SMatthew G. Knepley 
169d52c2f21SMatthew G. Knepley   Level: beginner
170d52c2f21SMatthew G. Knepley 
171d52c2f21SMatthew G. Knepley   Notes:
172d52c2f21SMatthew G. Knepley   Each field with name in `fieldnames` must be defined as having a data type of `PetscScalar`.
173d52c2f21SMatthew G. Knepley 
174d52c2f21SMatthew G. Knepley   This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`.
175d52c2f21SMatthew G. Knepley   Multiple calls to `DMSwarmVectorDefineField()` are permitted.
176d52c2f21SMatthew G. Knepley 
177d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
178d52c2f21SMatthew G. Knepley @*/
179*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineFields(DM sw, PetscInt Nf, const char *fieldnames[])
180d52c2f21SMatthew G. Knepley {
181*19307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
182*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
183b5bcf523SDave May 
184a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
185*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM);
186d52c2f21SMatthew G. Knepley   if (fieldnames) PetscAssertPointer(fieldnames, 3);
187*19307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
188*19307e5cSMatthew G. Knepley   PetscCheck(Nf >= 0, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields must be non-negative, not %" PetscInt_FMT, Nf);
189*19307e5cSMatthew G. Knepley   // Create a dummy cell DM if none has been specified (I think we should not support this mode)
190*19307e5cSMatthew G. Knepley   if (!swarm->activeCellDM) {
191*19307e5cSMatthew G. Knepley     DM            dm;
192*19307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
193b5bcf523SDave May 
194*19307e5cSMatthew G. Knepley     PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), &dm));
195*19307e5cSMatthew G. Knepley     PetscCall(DMSetType(dm, DMSHELL));
196*19307e5cSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, "dummy"));
197*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 0, NULL, &celldm));
198*19307e5cSMatthew G. Knepley     PetscCall(DMDestroy(&dm));
199*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmAddCellDM(sw, celldm));
200*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMDestroy(&celldm));
201*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmSetCellDMActive(sw, "dummy"));
202*19307e5cSMatthew G. Knepley   }
203*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
204*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) PetscCall(PetscFree(celldm->dmFields[f]));
205*19307e5cSMatthew G. Knepley   PetscCall(PetscFree(celldm->dmFields));
206*19307e5cSMatthew G. Knepley 
207*19307e5cSMatthew G. Knepley   celldm->Nf = Nf;
208*19307e5cSMatthew G. Knepley   PetscCall(PetscMalloc1(Nf, &celldm->dmFields));
209d52c2f21SMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
210d52c2f21SMatthew G. Knepley     PetscDataType type;
211d52c2f21SMatthew G. Knepley 
212d52c2f21SMatthew G. Knepley     // Check all fields are of type PETSC_REAL or PETSC_SCALAR
213*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], NULL, &type));
214*19307e5cSMatthew G. Knepley     PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
215*19307e5cSMatthew G. Knepley     PetscCall(PetscStrallocpy(fieldnames[f], (char **)&celldm->dmFields[f]));
216d52c2f21SMatthew G. Knepley   }
2173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
218b5bcf523SDave May }
219b5bcf523SDave May 
220cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
221*19307e5cSMatthew G. Knepley static PetscErrorCode DMCreateGlobalVector_Swarm(DM sw, Vec *vec)
222d71ae5a4SJacob Faibussowitsch {
223*19307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
224*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
225b5bcf523SDave May   Vec           x;
226b5bcf523SDave May   char          name[PETSC_MAX_PATH_LEN];
227*19307e5cSMatthew G. Knepley   PetscInt      bs = 0, n;
228b5bcf523SDave May 
229a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
230*19307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
231*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
232*19307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields");
233*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
234cc651181SDave May 
235d52c2f21SMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
236*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) {
237*19307e5cSMatthew G. Knepley     PetscInt fbs;
238d52c2f21SMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
239*19307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN));
240*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL));
241*19307e5cSMatthew G. Knepley     bs += fbs;
242d52c2f21SMatthew G. Knepley   }
243*19307e5cSMatthew G. Knepley   PetscCall(VecCreate(PetscObjectComm((PetscObject)sw), &x));
2449566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
245*19307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE));
246*19307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(x, bs));
247*19307e5cSMatthew G. Knepley   PetscCall(VecSetDM(x, sw));
2489566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
2499566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(x, VECOP_VIEW, (void (*)(void))VecView_Swarm));
250b5bcf523SDave May   *vec = x;
2513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
252b5bcf523SDave May }
253b5bcf523SDave May 
254b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
255*19307e5cSMatthew G. Knepley static PetscErrorCode DMCreateLocalVector_Swarm(DM sw, Vec *vec)
256d71ae5a4SJacob Faibussowitsch {
257*19307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
258*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
259b5bcf523SDave May   Vec           x;
260b5bcf523SDave May   char          name[PETSC_MAX_PATH_LEN];
261*19307e5cSMatthew G. Knepley   PetscInt      bs = 0, n;
262b5bcf523SDave May 
263a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
264*19307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
265*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
266*19307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields");
267*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
268cc651181SDave May 
269d52c2f21SMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
270*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) {
271*19307e5cSMatthew G. Knepley     PetscInt fbs;
272d52c2f21SMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
273*19307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN));
274*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL));
275*19307e5cSMatthew G. Knepley     bs += fbs;
276d52c2f21SMatthew G. Knepley   }
2779566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &x));
2789566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
279*19307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE));
280*19307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(x, bs));
281*19307e5cSMatthew G. Knepley   PetscCall(VecSetDM(x, sw));
2829566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
283b5bcf523SDave May   *vec = x;
2843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
285b5bcf523SDave May }
286b5bcf523SDave May 
287d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
288d71ae5a4SJacob Faibussowitsch {
289fb1bcc12SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
29077048351SPatrick Sanan   DMSwarmDataField gfield;
2912e956fe4SStefano Zampini   PetscInt         bs, nlocal, fid = -1, cfid = -2;
2922e956fe4SStefano Zampini   PetscBool        flg;
293d3a51819SDave May 
294fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
2952e956fe4SStefano Zampini   /* check vector is an inplace array */
2962e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
2972e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg));
298ea17275aSJose E. Roman   (void)flg; /* avoid compiler warning */
299e978a55eSPierre Jolivet   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);
3009566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(*vec, &nlocal));
3019566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(*vec, &bs));
30208401ef6SPierre 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");
3039566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
3049566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
3058df78e51SMark Adams   PetscCall(VecResetArray(*vec));
3069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(vec));
3073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
308fb1bcc12SMatthew G. Knepley }
309fb1bcc12SMatthew G. Knepley 
310d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
311d71ae5a4SJacob Faibussowitsch {
312fb1bcc12SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
313fb1bcc12SMatthew G. Knepley   PetscDataType type;
314fb1bcc12SMatthew G. Knepley   PetscScalar  *array;
3152e956fe4SStefano Zampini   PetscInt      bs, n, fid;
316fb1bcc12SMatthew G. Knepley   char          name[PETSC_MAX_PATH_LEN];
317e4fbd051SBarry Smith   PetscMPIInt   size;
3187f92dde0SRylanor   PetscBool     iscuda, iskokkos, iship;
319fb1bcc12SMatthew G. Knepley 
320fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
3219566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
3229566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
3239566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array));
32408401ef6SPierre Jolivet   PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
325fb1bcc12SMatthew G. Knepley 
3269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
3278df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos));
3288df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda));
3297f92dde0SRylanor   PetscCall(PetscStrcmp(dm->vectype, VECHIP, &iship));
3308df78e51SMark Adams   PetscCall(VecCreate(comm, vec));
3318df78e51SMark Adams   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
3328df78e51SMark Adams   PetscCall(VecSetBlockSize(*vec, bs));
3338df78e51SMark Adams   if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS));
3348df78e51SMark Adams   else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA));
3357f92dde0SRylanor   else if (iship) PetscCall(VecSetType(*vec, VECHIP));
3368df78e51SMark Adams   else PetscCall(VecSetType(*vec, VECSTANDARD));
3378df78e51SMark Adams   PetscCall(VecPlaceArray(*vec, array));
3388df78e51SMark Adams 
3399566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname));
3409566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
341fb1bcc12SMatthew G. Knepley 
342fb1bcc12SMatthew G. Knepley   /* Set guard */
3432e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
3442e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid));
34574d0cae8SMatthew G. Knepley 
3469566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*vec, dm));
3479566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm));
3483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
349fb1bcc12SMatthew G. Knepley }
350fb1bcc12SMatthew G. Knepley 
351*19307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], Vec *vec)
352*19307e5cSMatthew G. Knepley {
353*19307e5cSMatthew G. Knepley   DM_Swarm          *swarm = (DM_Swarm *)sw->data;
354*19307e5cSMatthew G. Knepley   const PetscScalar *array;
355*19307e5cSMatthew G. Knepley   PetscInt           bs, n, id = 0, cid = -2;
356*19307e5cSMatthew G. Knepley   PetscBool          flg;
357*19307e5cSMatthew G. Knepley 
358*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
359*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
360*19307e5cSMatthew G. Knepley     PetscInt fid;
361*19307e5cSMatthew G. Knepley 
362*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid));
363*19307e5cSMatthew G. Knepley     id += fid;
364*19307e5cSMatthew G. Knepley   }
365*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cid, flg));
366*19307e5cSMatthew G. Knepley   (void)flg; /* avoid compiler warning */
367*19307e5cSMatthew G. Knepley   PetscCheck(cid == id, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)! %" PetscInt_FMT " != %" PetscInt_FMT, fieldnames[0], cid, id);
368*19307e5cSMatthew G. Knepley   PetscCall(VecGetLocalSize(*vec, &n));
369*19307e5cSMatthew G. Knepley   PetscCall(VecGetBlockSize(*vec, &bs));
370*19307e5cSMatthew G. Knepley   n /= bs;
371*19307e5cSMatthew G. Knepley   PetscCheck(n == swarm->db->L, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid");
372*19307e5cSMatthew G. Knepley   PetscCall(VecGetArrayRead(*vec, &array));
373*19307e5cSMatthew G. Knepley   for (PetscInt f = 0, off = 0; f < Nf; ++f) {
374*19307e5cSMatthew G. Knepley     PetscScalar  *farray;
375*19307e5cSMatthew G. Knepley     PetscDataType ftype;
376*19307e5cSMatthew G. Knepley     PetscInt      fbs;
377*19307e5cSMatthew G. Knepley 
378*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
379*19307e5cSMatthew G. Knepley     PetscCheck(off + fbs <= bs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid blocksize %" PetscInt_FMT " < %" PetscInt_FMT, bs, off + fbs);
380*19307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i) {
381*19307e5cSMatthew G. Knepley       for (PetscInt b = 0; b < fbs; ++b) farray[i * fbs + b] = array[i * bs + off + b];
382*19307e5cSMatthew G. Knepley     }
383*19307e5cSMatthew G. Knepley     off += fbs;
384*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
385*19307e5cSMatthew G. Knepley   }
386*19307e5cSMatthew G. Knepley   PetscCall(VecRestoreArrayRead(*vec, &array));
387*19307e5cSMatthew G. Knepley   PetscCall(VecDestroy(vec));
388*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
389*19307e5cSMatthew G. Knepley }
390*19307e5cSMatthew G. Knepley 
391*19307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], MPI_Comm comm, Vec *vec)
392*19307e5cSMatthew G. Knepley {
393*19307e5cSMatthew G. Knepley   DM_Swarm    *swarm = (DM_Swarm *)sw->data;
394*19307e5cSMatthew G. Knepley   PetscScalar *array;
395*19307e5cSMatthew G. Knepley   PetscInt     n, bs = 0, id = 0;
396*19307e5cSMatthew G. Knepley   char         name[PETSC_MAX_PATH_LEN];
397*19307e5cSMatthew G. Knepley 
398*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
399*19307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
400*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
401*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
402*19307e5cSMatthew G. Knepley     PetscDataType ftype;
403*19307e5cSMatthew G. Knepley     PetscInt      fbs;
404*19307e5cSMatthew G. Knepley 
405*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], &fbs, &ftype));
406*19307e5cSMatthew G. Knepley     PetscCheck(ftype == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
407*19307e5cSMatthew G. Knepley     bs += fbs;
408*19307e5cSMatthew G. Knepley   }
409*19307e5cSMatthew G. Knepley 
410*19307e5cSMatthew G. Knepley   PetscCall(VecCreate(comm, vec));
411*19307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
412*19307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(*vec, bs));
413*19307e5cSMatthew G. Knepley   PetscCall(VecSetType(*vec, sw->vectype));
414*19307e5cSMatthew G. Knepley 
415*19307e5cSMatthew G. Knepley   PetscCall(VecGetArrayWrite(*vec, &array));
416*19307e5cSMatthew G. Knepley   for (PetscInt f = 0, off = 0; f < Nf; ++f) {
417*19307e5cSMatthew G. Knepley     PetscScalar  *farray;
418*19307e5cSMatthew G. Knepley     PetscDataType ftype;
419*19307e5cSMatthew G. Knepley     PetscInt      fbs;
420*19307e5cSMatthew G. Knepley 
421*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
422*19307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i) {
423*19307e5cSMatthew G. Knepley       for (PetscInt b = 0; b < fbs; ++b) array[i * bs + off + b] = farray[i * fbs + b];
424*19307e5cSMatthew G. Knepley     }
425*19307e5cSMatthew G. Knepley     off += fbs;
426*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
427*19307e5cSMatthew G. Knepley   }
428*19307e5cSMatthew G. Knepley   PetscCall(VecRestoreArrayWrite(*vec, &array));
429*19307e5cSMatthew G. Knepley 
430*19307e5cSMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
431*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
432*19307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
433*19307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, fieldnames[f], PETSC_MAX_PATH_LEN));
434*19307e5cSMatthew G. Knepley   }
435*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
436*19307e5cSMatthew G. Knepley 
437*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
438*19307e5cSMatthew G. Knepley     PetscInt fid;
439*19307e5cSMatthew G. Knepley 
440*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid));
441*19307e5cSMatthew G. Knepley     id += fid;
442*19307e5cSMatthew G. Knepley   }
443*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, id));
444*19307e5cSMatthew G. Knepley 
445*19307e5cSMatthew G. Knepley   PetscCall(VecSetDM(*vec, sw));
446*19307e5cSMatthew G. Knepley   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm));
447*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
448*19307e5cSMatthew G. Knepley }
449*19307e5cSMatthew G. Knepley 
4500643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
4510643ed39SMatthew G. Knepley 
4520643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
4530643ed39SMatthew G. Knepley 
4540643ed39SMatthew G. Knepley    and a particle function is given by
4550643ed39SMatthew G. Knepley 
4560643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
4570643ed39SMatthew G. Knepley 
4580643ed39SMatthew G. Knepley    then we want to require that
4590643ed39SMatthew G. Knepley 
4600643ed39SMatthew G. Knepley      M \hat f = M_p f
4610643ed39SMatthew G. Knepley 
4620643ed39SMatthew G. Knepley    where the particle mass matrix is given by
4630643ed39SMatthew G. Knepley 
4640643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
4650643ed39SMatthew G. Knepley 
4660643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
4670643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
4680643ed39SMatthew G. Knepley */
469d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
470d71ae5a4SJacob Faibussowitsch {
47183c47955SMatthew G. Knepley   const char   *name = "Mass Matrix";
4720643ed39SMatthew G. Knepley   MPI_Comm      comm;
473*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
47483c47955SMatthew G. Knepley   PetscDS       prob;
47583c47955SMatthew G. Knepley   PetscSection  fsection, globalFSection;
476e8f14785SLisandro Dalcin   PetscHSetIJ   ht;
4770643ed39SMatthew G. Knepley   PetscLayout   rLayout, colLayout;
47883c47955SMatthew G. Knepley   PetscInt     *dnz, *onz;
479adb2528bSMark Adams   PetscInt      locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4800643ed39SMatthew G. Knepley   PetscReal    *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
48183c47955SMatthew G. Knepley   PetscScalar  *elemMat;
482*19307e5cSMatthew G. Knepley   PetscInt      dim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0, totNc = 0;
483*19307e5cSMatthew G. Knepley   const char  **coordFields;
484*19307e5cSMatthew G. Knepley   PetscReal   **coordVals;
485*19307e5cSMatthew G. Knepley   PetscInt     *bs;
48683c47955SMatthew G. Knepley 
48783c47955SMatthew G. Knepley   PetscFunctionBegin;
4889566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
4899566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &dim));
4909566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
4919566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
4929566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
4939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ));
4949566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
4959566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
4969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
4979566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
49883c47955SMatthew G. Knepley 
499*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmc, &celldm));
500*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
501*19307e5cSMatthew G. Knepley   PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs));
502d52c2f21SMatthew G. Knepley 
5039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
5049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
5059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
5069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
5079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
5089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
5090643ed39SMatthew G. Knepley 
5109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
5119566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
5129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
5139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
5149566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
5159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
5160643ed39SMatthew G. Knepley 
5179566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
5189566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
51953e60ab4SJoseph Pusztay 
5209566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
521*19307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
5220bf7c1c5SMatthew G. Knepley     PetscObject  obj;
5230bf7c1c5SMatthew G. Knepley     PetscClassId id;
5240bf7c1c5SMatthew G. Knepley     PetscInt     Nc;
5250bf7c1c5SMatthew G. Knepley 
5260bf7c1c5SMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5270bf7c1c5SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
5280bf7c1c5SMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
5290bf7c1c5SMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
5300bf7c1c5SMatthew G. Knepley     totNc += Nc;
5310bf7c1c5SMatthew G. Knepley   }
5320643ed39SMatthew G. Knepley   /* count non-zeros */
5339566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
534*19307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
5350bf7c1c5SMatthew G. Knepley     PetscObject  obj;
5360bf7c1c5SMatthew G. Knepley     PetscClassId id;
5370bf7c1c5SMatthew G. Knepley     PetscInt     Nc;
5380bf7c1c5SMatthew G. Knepley 
5390bf7c1c5SMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5400bf7c1c5SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
5410bf7c1c5SMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
5420bf7c1c5SMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
5430bf7c1c5SMatthew G. Knepley 
544*19307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
5450643ed39SMatthew G. Knepley       PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */
54683c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
54783c47955SMatthew G. Knepley 
5489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5499566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
550fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
55183c47955SMatthew G. Knepley       {
552e8f14785SLisandro Dalcin         PetscHashIJKey key;
553e8f14785SLisandro Dalcin         PetscBool      missing;
5540bf7c1c5SMatthew G. Knepley         for (PetscInt i = 0; i < numFIndices; ++i) {
555adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
556adb2528bSMark Adams           if (key.j >= 0) {
55783c47955SMatthew G. Knepley             /* Get indices for coarse elements */
5580bf7c1c5SMatthew G. Knepley             for (PetscInt j = 0; j < numCIndices; ++j) {
5590bf7c1c5SMatthew G. Knepley               for (PetscInt c = 0; c < Nc; ++c) {
5600bf7c1c5SMatthew G. Knepley                 // TODO Need field offset on particle here
5610bf7c1c5SMatthew G. Knepley                 key.i = cindices[j] * totNc + c + rStart; /* global cols (from Swarm) */
562adb2528bSMark Adams                 if (key.i < 0) continue;
5639566063dSJacob Faibussowitsch                 PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
56483c47955SMatthew G. Knepley                 if (missing) {
5650643ed39SMatthew G. Knepley                   if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
566e8f14785SLisandro Dalcin                   else ++onz[key.i - rStart];
56763a3b9bcSJacob Faibussowitsch                 } else SETERRQ(PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j);
56883c47955SMatthew G. Knepley               }
569fc7c92abSMatthew G. Knepley             }
570fc7c92abSMatthew G. Knepley           }
5710bf7c1c5SMatthew G. Knepley         }
572fe11354eSMatthew G. Knepley         PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
57383c47955SMatthew G. Knepley       }
5749566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
57583c47955SMatthew G. Knepley     }
57683c47955SMatthew G. Knepley   }
5779566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
5789566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
5799566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
5809566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
5810bf7c1c5SMatthew G. Knepley   PetscCall(PetscMalloc3(maxC * totNc * totDim, &elemMat, maxC * totNc, &rowIDXs, maxC * dim, &xi));
582*19307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
583ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
58483c47955SMatthew G. Knepley     PetscObject     obj;
585ad9634fcSMatthew G. Knepley     PetscClassId    id;
586*19307e5cSMatthew G. Knepley     PetscInt        Nc;
58783c47955SMatthew G. Knepley 
5889566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
589ad9634fcSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
590ad9634fcSMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
591ad9634fcSMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
592ea7032a0SMatthew G. Knepley 
593*19307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
594*19307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
59583c47955SMatthew G. Knepley       PetscInt *findices, *cindices;
59683c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
59783c47955SMatthew G. Knepley 
5980643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5999566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
6009566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
6019566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
602*19307e5cSMatthew G. Knepley       for (PetscInt j = 0; j < numCIndices; ++j) {
603*19307e5cSMatthew G. Knepley         PetscReal xr[8];
604*19307e5cSMatthew G. Knepley         PetscInt  off = 0;
605*19307e5cSMatthew G. Knepley 
606*19307e5cSMatthew G. Knepley         for (PetscInt i = 0; i < Nfc; ++i) {
607*19307e5cSMatthew G. Knepley           for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[j] * bs[i] + b];
608*19307e5cSMatthew G. Knepley         }
609*19307e5cSMatthew G. Knepley         PetscCheck(off == dim, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The total block size of coordinates is %" PetscInt_FMT " != %" PetscInt_FMT " the DM coordinate dimension", off, dim);
610*19307e5cSMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, xr, &xi[j * dim]);
611*19307e5cSMatthew G. Knepley       }
612ad9634fcSMatthew G. Knepley       if (id == PETSCFE_CLASSID) PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
613ad9634fcSMatthew G. Knepley       else PetscCall(PetscFVCreateTabulation((PetscFV)obj, 1, numCIndices, xi, 0, &Tcoarse));
61483c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
6150bf7c1c5SMatthew G. Knepley       PetscCall(PetscArrayzero(elemMat, numCIndices * Nc * totDim));
6160bf7c1c5SMatthew G. Knepley       for (PetscInt i = 0; i < numFIndices / Nc; ++i) {
6170bf7c1c5SMatthew G. Knepley         for (PetscInt j = 0; j < numCIndices; ++j) {
6180bf7c1c5SMatthew G. Knepley           for (PetscInt c = 0; c < Nc; ++c) {
6190bf7c1c5SMatthew G. Knepley             // TODO Need field offset on particle and field here
6200643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
6210bf7c1c5SMatthew G. Knepley             elemMat[(j * totNc + c) * numFIndices + i * Nc + c] += Tcoarse->T[0][(j * numFIndices + i * Nc + c) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
62283c47955SMatthew G. Knepley           }
6230643ed39SMatthew G. Knepley         }
6240643ed39SMatthew G. Knepley       }
6250bf7c1c5SMatthew G. Knepley       for (PetscInt j = 0; j < numCIndices; ++j)
6260bf7c1c5SMatthew G. Knepley         // TODO Need field offset on particle here
6270bf7c1c5SMatthew G. Knepley         for (PetscInt c = 0; c < Nc; ++c) rowIDXs[j * Nc + c] = cindices[j] * totNc + c + rStart;
6280bf7c1c5SMatthew G. Knepley       if (0) PetscCall(DMPrintCellMatrix(cell, name, numCIndices * Nc, numFIndices, elemMat));
6290bf7c1c5SMatthew G. Knepley       PetscCall(MatSetValues(mass, numCIndices * Nc, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES));
630fe11354eSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
6319566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
6329566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
63383c47955SMatthew G. Knepley     }
634*19307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
63583c47955SMatthew G. Knepley   }
6369566063dSJacob Faibussowitsch   PetscCall(PetscFree3(elemMat, rowIDXs, xi));
6379566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
6389566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
639*19307e5cSMatthew G. Knepley   PetscCall(PetscFree2(coordVals, bs));
6409566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
6419566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
6423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64383c47955SMatthew G. Knepley }
64483c47955SMatthew G. Knepley 
645d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */
646d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m)
647d71ae5a4SJacob Faibussowitsch {
648d0c080abSJoseph Pusztay   Vec      field;
649d0c080abSJoseph Pusztay   PetscInt size;
650d0c080abSJoseph Pusztay 
651d0c080abSJoseph Pusztay   PetscFunctionBegin;
6529566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(sw, &field));
6539566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(field, &size));
6549566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(sw, &field));
6559566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, m));
6569566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*m));
6579566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size));
6589566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL));
6599566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(*m));
6609566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY));
6619566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY));
6629566063dSJacob Faibussowitsch   PetscCall(MatShift(*m, 1.0));
6639566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*m, sw));
6643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
665d0c080abSJoseph Pusztay }
666d0c080abSJoseph Pusztay 
667adb2528bSMark Adams /* FEM cols, Particle rows */
668d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
669d71ae5a4SJacob Faibussowitsch {
670*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
671895a1698SMatthew G. Knepley   PetscSection  gsf;
672*19307e5cSMatthew G. Knepley   PetscInt      m, n, Np, bs;
67383c47955SMatthew G. Knepley   void         *ctx;
67483c47955SMatthew G. Knepley 
67583c47955SMatthew G. Knepley   PetscFunctionBegin;
676*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmCoarse, &celldm));
677*19307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)dmCoarse), PETSC_ERR_USER, "Active cell DM does not define any fields");
6789566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
6799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
6800bf7c1c5SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dmCoarse, &Np));
681*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetBlockSize(celldm, dmCoarse, &bs));
682*19307e5cSMatthew G. Knepley   n = Np * bs;
6839566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
6849566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE));
6859566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
6869566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
68783c47955SMatthew G. Knepley 
6889566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
6899566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
6903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
69183c47955SMatthew G. Knepley }
69283c47955SMatthew G. Knepley 
693d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
694d71ae5a4SJacob Faibussowitsch {
6954cc7f7b2SMatthew G. Knepley   const char   *name = "Mass Matrix Square";
6964cc7f7b2SMatthew G. Knepley   MPI_Comm      comm;
697*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
6984cc7f7b2SMatthew G. Knepley   PetscDS       prob;
6994cc7f7b2SMatthew G. Knepley   PetscSection  fsection, globalFSection;
7004cc7f7b2SMatthew G. Knepley   PetscHSetIJ   ht;
7014cc7f7b2SMatthew G. Knepley   PetscLayout   rLayout, colLayout;
7024cc7f7b2SMatthew G. Knepley   PetscInt     *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
7034cc7f7b2SMatthew G. Knepley   PetscInt      locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
7044cc7f7b2SMatthew G. Knepley   PetscReal    *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
7054cc7f7b2SMatthew G. Knepley   PetscScalar  *elemMat, *elemMatSq;
706*19307e5cSMatthew G. Knepley   PetscInt      cdim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0;
707*19307e5cSMatthew G. Knepley   const char  **coordFields;
708*19307e5cSMatthew G. Knepley   PetscReal   **coordVals;
709*19307e5cSMatthew G. Knepley   PetscInt     *bs;
7104cc7f7b2SMatthew G. Knepley 
7114cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
7129566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
7139566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &cdim));
7149566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
7159566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
7169566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
7179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ));
7189566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
7199566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
7219566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
7224cc7f7b2SMatthew G. Knepley 
723*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmc, &celldm));
724*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
725*19307e5cSMatthew G. Knepley   PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs));
726d52c2f21SMatthew G. Knepley 
7279566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
7289566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
7299566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
7309566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
7319566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
7329566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
7334cc7f7b2SMatthew G. Knepley 
7349566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
7359566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
7369566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
7379566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
7389566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
7399566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
7404cc7f7b2SMatthew G. Knepley 
7419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmf, &depth));
7429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize));
7434cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth);
7449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxAdjSize, &adj));
7454cc7f7b2SMatthew G. Knepley 
7469566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
7479566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
7484cc7f7b2SMatthew G. Knepley   /* Count nonzeros
7494cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
7504cc7f7b2SMatthew G. Knepley   */
7519566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
752*19307e5cSMatthew G. Knepley   for (PetscInt cell = cStart; cell < cEnd; ++cell) {
7534cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
7544cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
7554cc7f7b2SMatthew G. Knepley #if 0
7564cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
7574cc7f7b2SMatthew G. Knepley #endif
7584cc7f7b2SMatthew G. Knepley 
7599566063dSJacob Faibussowitsch     PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
7604cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
7614cc7f7b2SMatthew G. Knepley     /* Diagonal block */
762*19307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices;
7634cc7f7b2SMatthew G. Knepley #if 0
7644cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
7659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj));
7664cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
7674cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
7684cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
7694cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
7704cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
7714cc7f7b2SMatthew G. Knepley 
7729566063dSJacob Faibussowitsch         PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
7734cc7f7b2SMatthew G. Knepley         {
7744cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
7754cc7f7b2SMatthew G. Knepley           PetscBool      missing;
7764cc7f7b2SMatthew G. Knepley 
7774cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
7784cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
7794cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
7804cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
7814cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
7824cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
7839566063dSJacob Faibussowitsch               PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
7844cc7f7b2SMatthew G. Knepley               if (missing) {
7854cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
7864cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
7874cc7f7b2SMatthew G. Knepley               }
7884cc7f7b2SMatthew G. Knepley             }
7894cc7f7b2SMatthew G. Knepley           }
7904cc7f7b2SMatthew G. Knepley         }
791fe11354eSMatthew G. Knepley         PetscCall(DMSwarmSortRestorePointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
7924cc7f7b2SMatthew G. Knepley       }
7934cc7f7b2SMatthew G. Knepley     }
7944cc7f7b2SMatthew G. Knepley #endif
795fe11354eSMatthew G. Knepley     PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
7964cc7f7b2SMatthew G. Knepley   }
7979566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
7989566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
7999566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
8009566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
8019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi));
8024cc7f7b2SMatthew G. Knepley   /* Fill in values
8034cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
8044cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
8054cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
8064cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
8074cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
8084cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
8094cc7f7b2SMatthew G. Knepley          Insert block
8104cc7f7b2SMatthew G. Knepley   */
811*19307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
8124cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
8134cc7f7b2SMatthew G. Knepley     PetscObject     obj;
814*19307e5cSMatthew G. Knepley     PetscInt        Nc;
8154cc7f7b2SMatthew G. Knepley 
8169566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
8179566063dSJacob Faibussowitsch     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
81863a3b9bcSJacob Faibussowitsch     PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc);
819*19307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
820*19307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
8214cc7f7b2SMatthew G. Knepley       PetscInt *findices, *cindices;
8224cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
8234cc7f7b2SMatthew G. Knepley 
8244cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
8259566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
8269566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
8279566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
828*19307e5cSMatthew G. Knepley       for (PetscInt p = 0; p < numCIndices; ++p) {
829*19307e5cSMatthew G. Knepley         PetscReal xr[8];
830*19307e5cSMatthew G. Knepley         PetscInt  off = 0;
831*19307e5cSMatthew G. Knepley 
832*19307e5cSMatthew G. Knepley         for (PetscInt i = 0; i < Nfc; ++i) {
833*19307e5cSMatthew G. Knepley           for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[p] * bs[i] + b];
834*19307e5cSMatthew G. Knepley         }
835*19307e5cSMatthew G. Knepley         PetscCheck(off == cdim, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The total block size of coordinates is %" PetscInt_FMT " != %" PetscInt_FMT " the DM coordinate dimension", off, cdim);
836*19307e5cSMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, xr, &xi[p * cdim]);
837*19307e5cSMatthew G. Knepley       }
8389566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
8394cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
8409566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elemMat, numCIndices * totDim));
841*19307e5cSMatthew G. Knepley       for (PetscInt i = 0; i < numFIndices; ++i) {
842*19307e5cSMatthew G. Knepley         for (PetscInt p = 0; p < numCIndices; ++p) {
843*19307e5cSMatthew G. Knepley           for (PetscInt c = 0; c < Nc; ++c) {
8444cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
8454cc7f7b2SMatthew G. Knepley             elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
8464cc7f7b2SMatthew G. Knepley           }
8474cc7f7b2SMatthew G. Knepley         }
8484cc7f7b2SMatthew G. Knepley       }
8499566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
850*19307e5cSMatthew G. Knepley       for (PetscInt p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
8519566063dSJacob Faibussowitsch       if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
8524cc7f7b2SMatthew G. Knepley       /* Block diagonal */
85378884ca7SMatthew G. Knepley       if (numCIndices) {
8544cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
8554cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
8564cc7f7b2SMatthew G. Knepley 
8579566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numCIndices, &blasn));
8589566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numFIndices, &blask));
859792fecdfSBarry Smith         PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn));
8604cc7f7b2SMatthew G. Knepley       }
8619566063dSJacob Faibussowitsch       PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES));
8624cf0e950SBarry Smith       /* TODO off-diagonal */
863fe11354eSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
8649566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
8654cc7f7b2SMatthew G. Knepley     }
866*19307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
8674cc7f7b2SMatthew G. Knepley   }
8689566063dSJacob Faibussowitsch   PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi));
8699566063dSJacob Faibussowitsch   PetscCall(PetscFree(adj));
8709566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
8719566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
872*19307e5cSMatthew G. Knepley   PetscCall(PetscFree2(coordVals, bs));
8739566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
8749566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
8753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8764cc7f7b2SMatthew G. Knepley }
8774cc7f7b2SMatthew G. Knepley 
878cc4c1da9SBarry Smith /*@
8794cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
8804cc7f7b2SMatthew G. Knepley 
88120f4b53cSBarry Smith   Collective
8824cc7f7b2SMatthew G. Knepley 
88360225df5SJacob Faibussowitsch   Input Parameters:
88420f4b53cSBarry Smith + dmCoarse - a `DMSWARM`
88520f4b53cSBarry Smith - dmFine   - a `DMPLEX`
8864cc7f7b2SMatthew G. Knepley 
88760225df5SJacob Faibussowitsch   Output Parameter:
8884cc7f7b2SMatthew G. Knepley . mass - the square of the particle mass matrix
8894cc7f7b2SMatthew G. Knepley 
8904cc7f7b2SMatthew G. Knepley   Level: advanced
8914cc7f7b2SMatthew G. Knepley 
89220f4b53cSBarry Smith   Note:
8934cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
8944cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
8954cc7f7b2SMatthew G. Knepley 
89620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMCreateMassMatrix()`
8974cc7f7b2SMatthew G. Knepley @*/
898d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
899d71ae5a4SJacob Faibussowitsch {
9004cc7f7b2SMatthew G. Knepley   PetscInt n;
9014cc7f7b2SMatthew G. Knepley   void    *ctx;
9024cc7f7b2SMatthew G. Knepley 
9034cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
9049566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dmCoarse, &n));
9059566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
9069566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE));
9079566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
9089566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
9094cc7f7b2SMatthew G. Knepley 
9109566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
9119566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view"));
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9134cc7f7b2SMatthew G. Knepley }
9144cc7f7b2SMatthew G. Knepley 
915cc4c1da9SBarry Smith /*@
91620f4b53cSBarry Smith   DMSwarmCreateGlobalVectorFromField - Creates a `Vec` object sharing the array associated with a given field
917d3a51819SDave May 
91820f4b53cSBarry Smith   Collective
919d3a51819SDave May 
92060225df5SJacob Faibussowitsch   Input Parameters:
92120f4b53cSBarry Smith + dm        - a `DMSWARM`
92262741f57SDave May - fieldname - the textual name given to a registered field
923d3a51819SDave May 
92460225df5SJacob Faibussowitsch   Output Parameter:
925d3a51819SDave May . vec - the vector
926d3a51819SDave May 
927d3a51819SDave May   Level: beginner
928d3a51819SDave May 
929cc4c1da9SBarry Smith   Note:
93020f4b53cSBarry Smith   The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromField()`.
9318b8a3813SDave May 
93220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()`
933d3a51819SDave May @*/
934d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
935d71ae5a4SJacob Faibussowitsch {
936fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
937b5bcf523SDave May 
938fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
939ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
9409566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
9413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
942b5bcf523SDave May }
943b5bcf523SDave May 
944cc4c1da9SBarry Smith /*@
94520f4b53cSBarry Smith   DMSwarmDestroyGlobalVectorFromField - Destroys the `Vec` object which share the array associated with a given field
946d3a51819SDave May 
94720f4b53cSBarry Smith   Collective
948d3a51819SDave May 
94960225df5SJacob Faibussowitsch   Input Parameters:
95020f4b53cSBarry Smith + dm        - a `DMSWARM`
95162741f57SDave May - fieldname - the textual name given to a registered field
952d3a51819SDave May 
95360225df5SJacob Faibussowitsch   Output Parameter:
954d3a51819SDave May . vec - the vector
955d3a51819SDave May 
956d3a51819SDave May   Level: beginner
957d3a51819SDave May 
95820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
959d3a51819SDave May @*/
960d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
961d71ae5a4SJacob Faibussowitsch {
962fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
963ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
9649566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
9653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
966b5bcf523SDave May }
967b5bcf523SDave May 
968cc4c1da9SBarry Smith /*@
96920f4b53cSBarry Smith   DMSwarmCreateLocalVectorFromField - Creates a `Vec` object sharing the array associated with a given field
970fb1bcc12SMatthew G. Knepley 
97120f4b53cSBarry Smith   Collective
972fb1bcc12SMatthew G. Knepley 
97360225df5SJacob Faibussowitsch   Input Parameters:
97420f4b53cSBarry Smith + dm        - a `DMSWARM`
97562741f57SDave May - fieldname - the textual name given to a registered field
976fb1bcc12SMatthew G. Knepley 
97760225df5SJacob Faibussowitsch   Output Parameter:
978fb1bcc12SMatthew G. Knepley . vec - the vector
979fb1bcc12SMatthew G. Knepley 
980fb1bcc12SMatthew G. Knepley   Level: beginner
981fb1bcc12SMatthew G. Knepley 
98220f4b53cSBarry Smith   Note:
9838b8a3813SDave May   The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
9848b8a3813SDave May 
98520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
986fb1bcc12SMatthew G. Knepley @*/
987d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
988d71ae5a4SJacob Faibussowitsch {
989fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
990bbe8250bSMatthew G. Knepley 
991fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
9929566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
9933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
994bbe8250bSMatthew G. Knepley }
995fb1bcc12SMatthew G. Knepley 
996cc4c1da9SBarry Smith /*@
99720f4b53cSBarry Smith   DMSwarmDestroyLocalVectorFromField - Destroys the `Vec` object which share the array associated with a given field
998fb1bcc12SMatthew G. Knepley 
99920f4b53cSBarry Smith   Collective
1000fb1bcc12SMatthew G. Knepley 
100160225df5SJacob Faibussowitsch   Input Parameters:
100220f4b53cSBarry Smith + dm        - a `DMSWARM`
100362741f57SDave May - fieldname - the textual name given to a registered field
1004fb1bcc12SMatthew G. Knepley 
100560225df5SJacob Faibussowitsch   Output Parameter:
1006fb1bcc12SMatthew G. Knepley . vec - the vector
1007fb1bcc12SMatthew G. Knepley 
1008fb1bcc12SMatthew G. Knepley   Level: beginner
1009fb1bcc12SMatthew G. Knepley 
101020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()`
1011fb1bcc12SMatthew G. Knepley @*/
1012d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
1013d71ae5a4SJacob Faibussowitsch {
1014fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
1015ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
10169566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
10173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1018bbe8250bSMatthew G. Knepley }
1019bbe8250bSMatthew G. Knepley 
1020cc4c1da9SBarry Smith /*@
1021*19307e5cSMatthew G. Knepley   DMSwarmCreateGlobalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set
1022*19307e5cSMatthew G. Knepley 
1023*19307e5cSMatthew G. Knepley   Collective
1024*19307e5cSMatthew G. Knepley 
1025*19307e5cSMatthew G. Knepley   Input Parameters:
1026*19307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
1027*19307e5cSMatthew G. Knepley . Nf         - the number of fields
1028*19307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
1029*19307e5cSMatthew G. Knepley 
1030*19307e5cSMatthew G. Knepley   Output Parameter:
1031*19307e5cSMatthew G. Knepley . vec - the vector
1032*19307e5cSMatthew G. Knepley 
1033*19307e5cSMatthew G. Knepley   Level: beginner
1034*19307e5cSMatthew G. Knepley 
1035*19307e5cSMatthew G. Knepley   Notes:
1036*19307e5cSMatthew G. Knepley   The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromFields()`.
1037*19307e5cSMatthew G. Knepley 
1038*19307e5cSMatthew G. Knepley   This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateGlobalVectorFromField()`
1039*19307e5cSMatthew G. Knepley 
1040*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromFields()`
1041*19307e5cSMatthew G. Knepley @*/
1042*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
1043*19307e5cSMatthew G. Knepley {
1044*19307e5cSMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
1045*19307e5cSMatthew G. Knepley 
1046*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
1047*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
1048*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec));
1049*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1050*19307e5cSMatthew G. Knepley }
1051*19307e5cSMatthew G. Knepley 
1052*19307e5cSMatthew G. Knepley /*@
1053*19307e5cSMatthew G. Knepley   DMSwarmDestroyGlobalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set
1054*19307e5cSMatthew G. Knepley 
1055*19307e5cSMatthew G. Knepley   Collective
1056*19307e5cSMatthew G. Knepley 
1057*19307e5cSMatthew G. Knepley   Input Parameters:
1058*19307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
1059*19307e5cSMatthew G. Knepley . Nf         - the number of fields
1060*19307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
1061*19307e5cSMatthew G. Knepley 
1062*19307e5cSMatthew G. Knepley   Output Parameter:
1063*19307e5cSMatthew G. Knepley . vec - the vector
1064*19307e5cSMatthew G. Knepley 
1065*19307e5cSMatthew G. Knepley   Level: beginner
1066*19307e5cSMatthew G. Knepley 
1067*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
1068*19307e5cSMatthew G. Knepley @*/
1069*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
1070*19307e5cSMatthew G. Knepley {
1071*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
1072*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
1073*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec));
1074*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1075*19307e5cSMatthew G. Knepley }
1076*19307e5cSMatthew G. Knepley 
1077*19307e5cSMatthew G. Knepley /*@
1078*19307e5cSMatthew G. Knepley   DMSwarmCreateLocalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set
1079*19307e5cSMatthew G. Knepley 
1080*19307e5cSMatthew G. Knepley   Collective
1081*19307e5cSMatthew G. Knepley 
1082*19307e5cSMatthew G. Knepley   Input Parameters:
1083*19307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
1084*19307e5cSMatthew G. Knepley . Nf         - the number of fields
1085*19307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
1086*19307e5cSMatthew G. Knepley 
1087*19307e5cSMatthew G. Knepley   Output Parameter:
1088*19307e5cSMatthew G. Knepley . vec - the vector
1089*19307e5cSMatthew G. Knepley 
1090*19307e5cSMatthew G. Knepley   Level: beginner
1091*19307e5cSMatthew G. Knepley 
1092*19307e5cSMatthew G. Knepley   Notes:
1093*19307e5cSMatthew G. Knepley   The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
1094*19307e5cSMatthew G. Knepley 
1095*19307e5cSMatthew G. Knepley   This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateLocalVectorFromField()`
1096*19307e5cSMatthew G. Knepley 
1097*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
1098*19307e5cSMatthew G. Knepley @*/
1099*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
1100*19307e5cSMatthew G. Knepley {
1101*19307e5cSMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
1102*19307e5cSMatthew G. Knepley 
1103*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
1104*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec));
1105*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1106*19307e5cSMatthew G. Knepley }
1107*19307e5cSMatthew G. Knepley 
1108*19307e5cSMatthew G. Knepley /*@
1109*19307e5cSMatthew G. Knepley   DMSwarmDestroyLocalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set
1110*19307e5cSMatthew G. Knepley 
1111*19307e5cSMatthew G. Knepley   Collective
1112*19307e5cSMatthew G. Knepley 
1113*19307e5cSMatthew G. Knepley   Input Parameters:
1114*19307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
1115*19307e5cSMatthew G. Knepley . Nf         - the number of fields
1116*19307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
1117*19307e5cSMatthew G. Knepley 
1118*19307e5cSMatthew G. Knepley   Output Parameter:
1119*19307e5cSMatthew G. Knepley . vec - the vector
1120*19307e5cSMatthew G. Knepley 
1121*19307e5cSMatthew G. Knepley   Level: beginner
1122*19307e5cSMatthew G. Knepley 
1123*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromFields()`
1124*19307e5cSMatthew G. Knepley @*/
1125*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
1126*19307e5cSMatthew G. Knepley {
1127*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
1128*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
1129*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec));
1130*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1131*19307e5cSMatthew G. Knepley }
1132*19307e5cSMatthew G. Knepley 
1133*19307e5cSMatthew G. Knepley /*@
113420f4b53cSBarry Smith   DMSwarmInitializeFieldRegister - Initiates the registration of fields to a `DMSWARM`
1135d3a51819SDave May 
113620f4b53cSBarry Smith   Collective
1137d3a51819SDave May 
113860225df5SJacob Faibussowitsch   Input Parameter:
113920f4b53cSBarry Smith . dm - a `DMSWARM`
1140d3a51819SDave May 
1141d3a51819SDave May   Level: beginner
1142d3a51819SDave May 
114320f4b53cSBarry Smith   Note:
114420f4b53cSBarry Smith   After all fields have been registered, you must call `DMSwarmFinalizeFieldRegister()`.
1145d3a51819SDave May 
114620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
1147db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1148d3a51819SDave May @*/
1149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
1150d71ae5a4SJacob Faibussowitsch {
11515f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
11523454631fSDave May 
1153521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1154cc651181SDave May   if (!swarm->field_registration_initialized) {
11555f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
1156da81f932SPierre Jolivet     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifier */
11579566063dSJacob Faibussowitsch     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT));  /* used for communication */
1158cc651181SDave May   }
11593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11605f50eb2eSDave May }
11615f50eb2eSDave May 
116274d0cae8SMatthew G. Knepley /*@
116320f4b53cSBarry Smith   DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a `DMSWARM`
1164d3a51819SDave May 
116520f4b53cSBarry Smith   Collective
1166d3a51819SDave May 
116760225df5SJacob Faibussowitsch   Input Parameter:
116820f4b53cSBarry Smith . dm - a `DMSWARM`
1169d3a51819SDave May 
1170d3a51819SDave May   Level: beginner
1171d3a51819SDave May 
117220f4b53cSBarry Smith   Note:
117320f4b53cSBarry Smith   After `DMSwarmFinalizeFieldRegister()` has been called, no new fields can be defined on the `DMSWARM`.
1174d3a51819SDave May 
117520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
1176db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1177d3a51819SDave May @*/
1178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
1179d71ae5a4SJacob Faibussowitsch {
11805f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
11816845f8f5SDave May 
1182521f74f9SMatthew G. Knepley   PetscFunctionBegin;
118348a46eb9SPierre Jolivet   if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db));
1184f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
11853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11865f50eb2eSDave May }
11875f50eb2eSDave May 
118874d0cae8SMatthew G. Knepley /*@
118920f4b53cSBarry Smith   DMSwarmSetLocalSizes - Sets the length of all registered fields on the `DMSWARM`
1190d3a51819SDave May 
119120f4b53cSBarry Smith   Not Collective
1192d3a51819SDave May 
119360225df5SJacob Faibussowitsch   Input Parameters:
119420f4b53cSBarry Smith + dm     - a `DMSWARM`
1195d3a51819SDave May . nlocal - the length of each registered field
119662741f57SDave May - buffer - the length of the buffer used to efficient dynamic re-sizing
1197d3a51819SDave May 
1198d3a51819SDave May   Level: beginner
1199d3a51819SDave May 
120020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`
1201d3a51819SDave May @*/
1202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetLocalSizes(DM dm, PetscInt nlocal, PetscInt buffer)
1203d71ae5a4SJacob Faibussowitsch {
12045f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
12055f50eb2eSDave May 
1206521f74f9SMatthew G. Knepley   PetscFunctionBegin;
12079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0));
12089566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer));
12099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0));
12103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12115f50eb2eSDave May }
12125f50eb2eSDave May 
121374d0cae8SMatthew G. Knepley /*@
121420f4b53cSBarry Smith   DMSwarmSetCellDM - Attaches a `DM` to a `DMSWARM`
1215d3a51819SDave May 
121620f4b53cSBarry Smith   Collective
1217d3a51819SDave May 
121860225df5SJacob Faibussowitsch   Input Parameters:
1219*19307e5cSMatthew G. Knepley + sw - a `DMSWARM`
1220*19307e5cSMatthew G. Knepley - dm - the `DM` to attach to the `DMSWARM`
1221d3a51819SDave May 
1222d3a51819SDave May   Level: beginner
1223d3a51819SDave May 
122420f4b53cSBarry Smith   Note:
1225*19307e5cSMatthew G. Knepley   The attached `DM` (dm) will be queried for point location and
122620f4b53cSBarry Smith   neighbor MPI-rank information if `DMSwarmMigrate()` is called.
1227d3a51819SDave May 
122820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()`
1229d3a51819SDave May @*/
1230*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM sw, DM dm)
1231d71ae5a4SJacob Faibussowitsch {
1232*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
1233*19307e5cSMatthew G. Knepley   const char   *name;
1234*19307e5cSMatthew G. Knepley   char         *coordName;
1235d52c2f21SMatthew G. Knepley 
1236d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
1237d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1238*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
1239*19307e5cSMatthew G. Knepley   PetscCall(PetscStrallocpy(DMSwarmPICField_coor, &coordName));
1240*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 1, (const char **)&coordName, &celldm));
1241*19307e5cSMatthew G. Knepley   PetscCall(PetscFree(coordName));
1242*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
1243*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmAddCellDM(sw, celldm));
1244*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMDestroy(&celldm));
1245*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(sw, name));
1246d52c2f21SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1247d52c2f21SMatthew G. Knepley }
1248d52c2f21SMatthew G. Knepley 
1249d52c2f21SMatthew G. Knepley /*@
1250*19307e5cSMatthew G. Knepley   DMSwarmGetCellDM - Fetches the active cell `DM`
1251d52c2f21SMatthew G. Knepley 
1252d52c2f21SMatthew G. Knepley   Collective
1253d52c2f21SMatthew G. Knepley 
1254d52c2f21SMatthew G. Knepley   Input Parameter:
1255d52c2f21SMatthew G. Knepley . sw - a `DMSWARM`
1256d52c2f21SMatthew G. Knepley 
1257*19307e5cSMatthew G. Knepley   Output Parameter:
1258*19307e5cSMatthew G. Knepley . dm - the active `DM` for the `DMSWARM`
1259*19307e5cSMatthew G. Knepley 
1260d52c2f21SMatthew G. Knepley   Level: beginner
1261d52c2f21SMatthew G. Knepley 
1262*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`
1263d52c2f21SMatthew G. Knepley @*/
1264*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM sw, DM *dm)
1265d52c2f21SMatthew G. Knepley {
1266d52c2f21SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
1267*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
1268*19307e5cSMatthew G. Knepley 
1269*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
1270*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)&celldm));
1271*19307e5cSMatthew G. Knepley   PetscCheck(celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "There is no cell DM named %s in this Swarm", swarm->activeCellDM);
1272*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetDM(celldm, dm));
1273*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1274*19307e5cSMatthew G. Knepley }
1275*19307e5cSMatthew G. Knepley 
1276*19307e5cSMatthew G. Knepley /*@
1277*19307e5cSMatthew G. Knepley   DMSwarmSetCellDMActive - Activates a cell `DM` for a `DMSWARM`
1278*19307e5cSMatthew G. Knepley 
1279*19307e5cSMatthew G. Knepley   Collective
1280*19307e5cSMatthew G. Knepley 
1281*19307e5cSMatthew G. Knepley   Input Parameters:
1282*19307e5cSMatthew G. Knepley + sw   - a `DMSWARM`
1283*19307e5cSMatthew G. Knepley - name - name of the cell `DM` to active for the `DMSWARM`
1284*19307e5cSMatthew G. Knepley 
1285*19307e5cSMatthew G. Knepley   Level: beginner
1286*19307e5cSMatthew G. Knepley 
1287*19307e5cSMatthew G. Knepley   Note:
1288*19307e5cSMatthew G. Knepley   The attached `DM` (dmcell) will be queried for point location and
1289*19307e5cSMatthew G. Knepley   neighbor MPI-rank information if `DMSwarmMigrate()` is called.
1290*19307e5cSMatthew G. Knepley 
1291*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
1292*19307e5cSMatthew G. Knepley @*/
1293*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDMActive(DM sw, const char name[])
1294*19307e5cSMatthew G. Knepley {
1295*19307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
1296*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
1297d52c2f21SMatthew G. Knepley 
1298d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
1299d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1300*19307e5cSMatthew G. Knepley   PetscCall(PetscInfo(sw, "Setting cell DM to %s\n", name));
1301*19307e5cSMatthew G. Knepley   PetscCall(PetscFree(swarm->activeCellDM));
1302*19307e5cSMatthew G. Knepley   PetscCall(PetscStrallocpy(name, (char **)&swarm->activeCellDM));
1303*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
1304*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1305d52c2f21SMatthew G. Knepley }
1306*19307e5cSMatthew G. Knepley 
1307*19307e5cSMatthew G. Knepley /*@
1308*19307e5cSMatthew G. Knepley   DMSwarmGetCellDMActive - Returns the active cell `DM` for a `DMSWARM`
1309*19307e5cSMatthew G. Knepley 
1310*19307e5cSMatthew G. Knepley   Collective
1311*19307e5cSMatthew G. Knepley 
1312*19307e5cSMatthew G. Knepley   Input Parameter:
1313*19307e5cSMatthew G. Knepley . sw - a `DMSWARM`
1314*19307e5cSMatthew G. Knepley 
1315*19307e5cSMatthew G. Knepley   Output Parameter:
1316*19307e5cSMatthew G. Knepley . celldm - the active `DMSwarmCellDM`
1317*19307e5cSMatthew G. Knepley 
1318*19307e5cSMatthew G. Knepley   Level: beginner
1319*19307e5cSMatthew G. Knepley 
1320*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
1321*19307e5cSMatthew G. Knepley @*/
1322*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMActive(DM sw, DMSwarmCellDM *celldm)
1323*19307e5cSMatthew G. Knepley {
1324*19307e5cSMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
1325*19307e5cSMatthew G. Knepley 
1326*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
1327*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1328*19307e5cSMatthew G. Knepley   PetscCheck(swarm->activeCellDM, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no active cell DM");
1329*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)celldm));
1330*19307e5cSMatthew G. Knepley   PetscCheck(*celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has invalid cell DM for %s", swarm->activeCellDM);
1331*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1332*19307e5cSMatthew G. Knepley }
1333*19307e5cSMatthew G. Knepley 
1334*19307e5cSMatthew G. Knepley /*@
1335*19307e5cSMatthew G. Knepley   DMSwarmAddCellDM - Adds a cell `DM` to the `DMSWARM`
1336*19307e5cSMatthew G. Knepley 
1337*19307e5cSMatthew G. Knepley   Collective
1338*19307e5cSMatthew G. Knepley 
1339*19307e5cSMatthew G. Knepley   Input Parameters:
1340*19307e5cSMatthew G. Knepley + sw     - a `DMSWARM`
1341*19307e5cSMatthew G. Knepley - celldm - the `DMSwarmCellDM`
1342*19307e5cSMatthew G. Knepley 
1343*19307e5cSMatthew G. Knepley   Level: beginner
1344*19307e5cSMatthew G. Knepley 
1345*19307e5cSMatthew G. Knepley   Note:
1346*19307e5cSMatthew G. Knepley   Cell DMs with the same name will share the cellid field
1347*19307e5cSMatthew G. Knepley 
1348*19307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmPushCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
1349*19307e5cSMatthew G. Knepley @*/
1350*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmAddCellDM(DM sw, DMSwarmCellDM celldm)
1351*19307e5cSMatthew G. Knepley {
1352*19307e5cSMatthew G. Knepley   DM_Swarm   *swarm = (DM_Swarm *)sw->data;
1353*19307e5cSMatthew G. Knepley   const char *name;
1354*19307e5cSMatthew G. Knepley   PetscInt    dim;
1355*19307e5cSMatthew G. Knepley   PetscBool   flg;
1356*19307e5cSMatthew G. Knepley   MPI_Comm    comm;
1357*19307e5cSMatthew G. Knepley 
1358*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
1359*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1360*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
1361*19307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(celldm, DMSWARMCELLDM_CLASSID, 2);
1362*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
1363*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectListAdd(&swarm->cellDMs, name, (PetscObject)celldm));
1364*19307e5cSMatthew G. Knepley   PetscCall(DMGetDimension(sw, &dim));
1365*19307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nfc; ++f) {
1366*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataFieldStringInList(celldm->coordFields[f], swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg));
1367*19307e5cSMatthew G. Knepley     if (!flg) {
1368*19307e5cSMatthew G. Knepley       PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->coordFields[f], dim, PETSC_DOUBLE));
1369*19307e5cSMatthew G. Knepley     } else {
1370*19307e5cSMatthew G. Knepley       PetscDataType dt;
1371*19307e5cSMatthew G. Knepley       PetscInt      bs;
1372*19307e5cSMatthew G. Knepley 
1373*19307e5cSMatthew G. Knepley       PetscCall(DMSwarmGetFieldInfo(sw, celldm->coordFields[f], &bs, &dt));
1374*19307e5cSMatthew G. Knepley       PetscCheck(bs == dim, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s has blocksize %" PetscInt_FMT " != %" PetscInt_FMT " spatial dimension", celldm->coordFields[f], bs, dim);
1375*19307e5cSMatthew G. Knepley       PetscCheck(dt == PETSC_DOUBLE, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s has datatype %s != PETSC_DOUBLE", celldm->coordFields[f], PetscDataTypes[dt]);
1376*19307e5cSMatthew G. Knepley     }
1377*19307e5cSMatthew G. Knepley   }
1378*19307e5cSMatthew G. Knepley   // Assume that DMs with the same name share the cellid field
1379*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataFieldStringInList(celldm->cellid, swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg));
1380*19307e5cSMatthew G. Knepley   if (!flg) {
1381*19307e5cSMatthew G. Knepley     PetscBool   isShell, isDummy;
1382*19307e5cSMatthew G. Knepley     const char *name;
1383*19307e5cSMatthew G. Knepley 
1384*19307e5cSMatthew G. Knepley     // Allow dummy DMSHELL (I don't think we should support this mode)
1385*19307e5cSMatthew G. Knepley     PetscCall(PetscObjectTypeCompare((PetscObject)celldm->dm, DMSHELL, &isShell));
1386*19307e5cSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)celldm->dm, &name));
1387*19307e5cSMatthew G. Knepley     PetscCall(PetscStrcmp(name, "dummy", &isDummy));
1388*19307e5cSMatthew G. Knepley     if (!isShell || !isDummy) PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->cellid, 1, PETSC_INT));
1389*19307e5cSMatthew G. Knepley   }
1390*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(sw, name));
13913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1392fe39f135SDave May }
1393fe39f135SDave May 
139474d0cae8SMatthew G. Knepley /*@
1395d5b43468SJose E. Roman   DMSwarmGetLocalSize - Retrieves the local length of fields registered
1396d3a51819SDave May 
139720f4b53cSBarry Smith   Not Collective
1398d3a51819SDave May 
139960225df5SJacob Faibussowitsch   Input Parameter:
140020f4b53cSBarry Smith . dm - a `DMSWARM`
1401d3a51819SDave May 
140260225df5SJacob Faibussowitsch   Output Parameter:
1403d3a51819SDave May . nlocal - the length of each registered field
1404d3a51819SDave May 
1405d3a51819SDave May   Level: beginner
1406d3a51819SDave May 
140720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()`
1408d3a51819SDave May @*/
1409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal)
1410d71ae5a4SJacob Faibussowitsch {
1411dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1412dcf43ee8SDave May 
1413521f74f9SMatthew G. Knepley   PetscFunctionBegin;
14149566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL));
14153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1416dcf43ee8SDave May }
1417dcf43ee8SDave May 
141874d0cae8SMatthew G. Knepley /*@
1419d5b43468SJose E. Roman   DMSwarmGetSize - Retrieves the total length of fields registered
1420d3a51819SDave May 
142120f4b53cSBarry Smith   Collective
1422d3a51819SDave May 
142360225df5SJacob Faibussowitsch   Input Parameter:
142420f4b53cSBarry Smith . dm - a `DMSWARM`
1425d3a51819SDave May 
142660225df5SJacob Faibussowitsch   Output Parameter:
1427d3a51819SDave May . n - the total length of each registered field
1428d3a51819SDave May 
1429d3a51819SDave May   Level: beginner
1430d3a51819SDave May 
1431d3a51819SDave May   Note:
143220f4b53cSBarry Smith   This calls `MPI_Allreduce()` upon each call (inefficient but safe)
1433d3a51819SDave May 
143420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()`
1435d3a51819SDave May @*/
1436d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n)
1437d71ae5a4SJacob Faibussowitsch {
1438dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
14395627991aSBarry Smith   PetscInt  nlocal;
1440dcf43ee8SDave May 
1441521f74f9SMatthew G. Knepley   PetscFunctionBegin;
14429566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1443462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
14443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1445dcf43ee8SDave May }
1446dcf43ee8SDave May 
1447cc4c1da9SBarry Smith /*@
144820f4b53cSBarry Smith   DMSwarmRegisterPetscDatatypeField - Register a field to a `DMSWARM` with a native PETSc data type
1449d3a51819SDave May 
145020f4b53cSBarry Smith   Collective
1451d3a51819SDave May 
145260225df5SJacob Faibussowitsch   Input Parameters:
145320f4b53cSBarry Smith + dm        - a `DMSWARM`
1454d3a51819SDave May . fieldname - the textual name to identify this field
1455d3a51819SDave May . blocksize - the number of each data type
145620f4b53cSBarry Smith - type      - a valid PETSc data type (`PETSC_CHAR`, `PETSC_SHORT`, `PETSC_INT`, `PETSC_FLOAT`, `PETSC_REAL`, `PETSC_LONG`)
1457d3a51819SDave May 
1458d3a51819SDave May   Level: beginner
1459d3a51819SDave May 
1460d3a51819SDave May   Notes:
14618b8a3813SDave May   The textual name for each registered field must be unique.
1462d3a51819SDave May 
146320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1464d3a51819SDave May @*/
1465d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type)
1466d71ae5a4SJacob Faibussowitsch {
1467b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1468b62e03f8SDave May   size_t    size;
1469b62e03f8SDave May 
1470521f74f9SMatthew G. Knepley   PetscFunctionBegin;
147128b400f6SJacob Faibussowitsch   PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first");
147228b400f6SJacob Faibussowitsch   PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
14735f50eb2eSDave May 
147408401ef6SPierre Jolivet   PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
147508401ef6SPierre Jolivet   PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
147608401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
147708401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
147808401ef6SPierre Jolivet   PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
1479b62e03f8SDave May 
14809566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &size));
1481b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
14829566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL));
148352c3ed93SDave May   {
148477048351SPatrick Sanan     DMSwarmDataField gfield;
148552c3ed93SDave May 
14869566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
14879566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
148852c3ed93SDave May   }
1489b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = type;
14903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1491b62e03f8SDave May }
1492b62e03f8SDave May 
1493d3a51819SDave May /*@C
149420f4b53cSBarry Smith   DMSwarmRegisterUserStructField - Register a user defined struct to a `DMSWARM`
1495d3a51819SDave May 
149620f4b53cSBarry Smith   Collective
1497d3a51819SDave May 
149860225df5SJacob Faibussowitsch   Input Parameters:
149920f4b53cSBarry Smith + dm        - a `DMSWARM`
1500d3a51819SDave May . fieldname - the textual name to identify this field
150162741f57SDave May - size      - the size in bytes of the user struct of each data type
1502d3a51819SDave May 
1503d3a51819SDave May   Level: beginner
1504d3a51819SDave May 
150520f4b53cSBarry Smith   Note:
15068b8a3813SDave May   The textual name for each registered field must be unique.
1507d3a51819SDave May 
150820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()`
1509d3a51819SDave May @*/
1510d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size)
1511d71ae5a4SJacob Faibussowitsch {
1512b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1513b62e03f8SDave May 
1514521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15159566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL));
1516b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT;
15173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1518b62e03f8SDave May }
1519b62e03f8SDave May 
1520d3a51819SDave May /*@C
152120f4b53cSBarry Smith   DMSwarmRegisterUserDatatypeField - Register a user defined data type to a `DMSWARM`
1522d3a51819SDave May 
152320f4b53cSBarry Smith   Collective
1524d3a51819SDave May 
152560225df5SJacob Faibussowitsch   Input Parameters:
152620f4b53cSBarry Smith + dm        - a `DMSWARM`
1527d3a51819SDave May . fieldname - the textual name to identify this field
1528d3a51819SDave May . size      - the size in bytes of the user data type
152962741f57SDave May - blocksize - the number of each data type
1530d3a51819SDave May 
1531d3a51819SDave May   Level: beginner
1532d3a51819SDave May 
153320f4b53cSBarry Smith   Note:
15348b8a3813SDave May   The textual name for each registered field must be unique.
1535d3a51819SDave May 
153642747ad1SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()`
1537d3a51819SDave May @*/
1538d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize)
1539d71ae5a4SJacob Faibussowitsch {
1540b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1541b62e03f8SDave May 
1542521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15439566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL));
1544320740a0SDave May   {
154577048351SPatrick Sanan     DMSwarmDataField gfield;
1546320740a0SDave May 
15479566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
15489566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
1549320740a0SDave May   }
1550b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
15513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1552b62e03f8SDave May }
1553b62e03f8SDave May 
1554d3a51819SDave May /*@C
1555d3a51819SDave May   DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1556d3a51819SDave May 
1557cc4c1da9SBarry Smith   Not Collective, No Fortran Support
1558d3a51819SDave May 
155960225df5SJacob Faibussowitsch   Input Parameters:
156020f4b53cSBarry Smith + dm        - a `DMSWARM`
156162741f57SDave May - fieldname - the textual name to identify this field
1562d3a51819SDave May 
156360225df5SJacob Faibussowitsch   Output Parameters:
156462741f57SDave May + blocksize - the number of each data type
1565d3a51819SDave May . type      - the data type
156662741f57SDave May - data      - pointer to raw array
1567d3a51819SDave May 
1568d3a51819SDave May   Level: beginner
1569d3a51819SDave May 
1570d3a51819SDave May   Notes:
157120f4b53cSBarry Smith   The array must be returned using a matching call to `DMSwarmRestoreField()`.
1572d3a51819SDave May 
157320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreField()`
1574d3a51819SDave May @*/
1575d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data)
1576d71ae5a4SJacob Faibussowitsch {
1577b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
157877048351SPatrick Sanan   DMSwarmDataField gfield;
1579b62e03f8SDave May 
1580521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1581ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
15829566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
15839566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
15849566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetAccess(gfield));
15859566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetEntries(gfield, data));
1586ad540459SPierre Jolivet   if (blocksize) *blocksize = gfield->bs;
1587ad540459SPierre Jolivet   if (type) *type = gfield->petsc_type;
15883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1589b62e03f8SDave May }
1590b62e03f8SDave May 
1591d3a51819SDave May /*@C
1592d3a51819SDave May   DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1593d3a51819SDave May 
1594cc4c1da9SBarry Smith   Not Collective, No Fortran Support
1595d3a51819SDave May 
159660225df5SJacob Faibussowitsch   Input Parameters:
159720f4b53cSBarry Smith + dm        - a `DMSWARM`
159862741f57SDave May - fieldname - the textual name to identify this field
1599d3a51819SDave May 
160060225df5SJacob Faibussowitsch   Output Parameters:
160162741f57SDave May + blocksize - the number of each data type
1602d3a51819SDave May . type      - the data type
160362741f57SDave May - data      - pointer to raw array
1604d3a51819SDave May 
1605d3a51819SDave May   Level: beginner
1606d3a51819SDave May 
1607d3a51819SDave May   Notes:
160820f4b53cSBarry Smith   The user must call `DMSwarmGetField()` prior to calling `DMSwarmRestoreField()`.
1609d3a51819SDave May 
161020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetField()`
1611d3a51819SDave May @*/
1612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data)
1613d71ae5a4SJacob Faibussowitsch {
1614b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
161577048351SPatrick Sanan   DMSwarmDataField gfield;
1616b62e03f8SDave May 
1617521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1618ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
16199566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
16209566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
1621b62e03f8SDave May   if (data) *data = NULL;
16223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1623b62e03f8SDave May }
1624b62e03f8SDave May 
16250bf7c1c5SMatthew G. Knepley PetscErrorCode DMSwarmGetFieldInfo(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type)
16260bf7c1c5SMatthew G. Knepley {
16270bf7c1c5SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
16280bf7c1c5SMatthew G. Knepley   DMSwarmDataField gfield;
16290bf7c1c5SMatthew G. Knepley 
16300bf7c1c5SMatthew G. Knepley   PetscFunctionBegin;
16310bf7c1c5SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
16320bf7c1c5SMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
16330bf7c1c5SMatthew G. Knepley   if (blocksize) *blocksize = gfield->bs;
16340bf7c1c5SMatthew G. Knepley   if (type) *type = gfield->petsc_type;
16350bf7c1c5SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
16360bf7c1c5SMatthew G. Knepley }
16370bf7c1c5SMatthew G. Knepley 
163874d0cae8SMatthew G. Knepley /*@
163920f4b53cSBarry Smith   DMSwarmAddPoint - Add space for one new point in the `DMSWARM`
1640d3a51819SDave May 
164120f4b53cSBarry Smith   Not Collective
1642d3a51819SDave May 
164360225df5SJacob Faibussowitsch   Input Parameter:
164420f4b53cSBarry Smith . dm - a `DMSWARM`
1645d3a51819SDave May 
1646d3a51819SDave May   Level: beginner
1647d3a51819SDave May 
1648d3a51819SDave May   Notes:
16498b8a3813SDave May   The new point will have all fields initialized to zero.
1650d3a51819SDave May 
165120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddNPoints()`
1652d3a51819SDave May @*/
1653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddPoint(DM dm)
1654d71ae5a4SJacob Faibussowitsch {
1655cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1656cb1d1399SDave May 
1657521f74f9SMatthew G. Knepley   PetscFunctionBegin;
16589566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
16599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
16609566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketAddPoint(swarm->db));
16619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
16623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1663cb1d1399SDave May }
1664cb1d1399SDave May 
166574d0cae8SMatthew G. Knepley /*@
166620f4b53cSBarry Smith   DMSwarmAddNPoints - Add space for a number of new points in the `DMSWARM`
1667d3a51819SDave May 
166820f4b53cSBarry Smith   Not Collective
1669d3a51819SDave May 
167060225df5SJacob Faibussowitsch   Input Parameters:
167120f4b53cSBarry Smith + dm      - a `DMSWARM`
167262741f57SDave May - npoints - the number of new points to add
1673d3a51819SDave May 
1674d3a51819SDave May   Level: beginner
1675d3a51819SDave May 
1676d3a51819SDave May   Notes:
16778b8a3813SDave May   The new point will have all fields initialized to zero.
1678d3a51819SDave May 
167920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddPoint()`
1680d3a51819SDave May @*/
1681d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints)
1682d71ae5a4SJacob Faibussowitsch {
1683cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1684cb1d1399SDave May   PetscInt  nlocal;
1685cb1d1399SDave May 
1686521f74f9SMatthew G. Knepley   PetscFunctionBegin;
16879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
16889566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1689cb1d1399SDave May   nlocal = nlocal + npoints;
16909566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
16919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
16923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1693cb1d1399SDave May }
1694cb1d1399SDave May 
169574d0cae8SMatthew G. Knepley /*@
169620f4b53cSBarry Smith   DMSwarmRemovePoint - Remove the last point from the `DMSWARM`
1697d3a51819SDave May 
169820f4b53cSBarry Smith   Not Collective
1699d3a51819SDave May 
170060225df5SJacob Faibussowitsch   Input Parameter:
170120f4b53cSBarry Smith . dm - a `DMSWARM`
1702d3a51819SDave May 
1703d3a51819SDave May   Level: beginner
1704d3a51819SDave May 
170520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePointAtIndex()`
1706d3a51819SDave May @*/
1707d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePoint(DM dm)
1708d71ae5a4SJacob Faibussowitsch {
1709cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1710cb1d1399SDave May 
1711521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
17139566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePoint(swarm->db));
17149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
17153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1716cb1d1399SDave May }
1717cb1d1399SDave May 
171874d0cae8SMatthew G. Knepley /*@
171920f4b53cSBarry Smith   DMSwarmRemovePointAtIndex - Removes a specific point from the `DMSWARM`
1720d3a51819SDave May 
172120f4b53cSBarry Smith   Not Collective
1722d3a51819SDave May 
172360225df5SJacob Faibussowitsch   Input Parameters:
172420f4b53cSBarry Smith + dm  - a `DMSWARM`
172562741f57SDave May - idx - index of point to remove
1726d3a51819SDave May 
1727d3a51819SDave May   Level: beginner
1728d3a51819SDave May 
172920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()`
1730d3a51819SDave May @*/
1731d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx)
1732d71ae5a4SJacob Faibussowitsch {
1733cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1734cb1d1399SDave May 
1735521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17369566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
17379566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx));
17389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
17393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1740cb1d1399SDave May }
1741b62e03f8SDave May 
174274d0cae8SMatthew G. Knepley /*@
174320f4b53cSBarry Smith   DMSwarmCopyPoint - Copy point pj to point pi in the `DMSWARM`
1744ba4fc9c6SDave May 
174520f4b53cSBarry Smith   Not Collective
1746ba4fc9c6SDave May 
174760225df5SJacob Faibussowitsch   Input Parameters:
174820f4b53cSBarry Smith + dm - a `DMSWARM`
1749ba4fc9c6SDave May . pi - the index of the point to copy
1750ba4fc9c6SDave May - pj - the point index where the copy should be located
1751ba4fc9c6SDave May 
1752ba4fc9c6SDave May   Level: beginner
1753ba4fc9c6SDave May 
175420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()`
1755ba4fc9c6SDave May @*/
1756d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj)
1757d71ae5a4SJacob Faibussowitsch {
1758ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1759ba4fc9c6SDave May 
1760ba4fc9c6SDave May   PetscFunctionBegin;
17619566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
17629566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj));
17633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1764ba4fc9c6SDave May }
1765ba4fc9c6SDave May 
176666976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points)
1767d71ae5a4SJacob Faibussowitsch {
1768521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17699566063dSJacob Faibussowitsch   PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points));
17703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17713454631fSDave May }
17723454631fSDave May 
177374d0cae8SMatthew G. Knepley /*@
177420f4b53cSBarry Smith   DMSwarmMigrate - Relocates points defined in the `DMSWARM` to other MPI-ranks
1775d3a51819SDave May 
177620f4b53cSBarry Smith   Collective
1777d3a51819SDave May 
177860225df5SJacob Faibussowitsch   Input Parameters:
177920f4b53cSBarry Smith + dm                 - the `DMSWARM`
178062741f57SDave May - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1781d3a51819SDave May 
1782d3a51819SDave May   Level: advanced
1783d3a51819SDave May 
178420f4b53cSBarry Smith   Notes:
178520f4b53cSBarry Smith   The `DM` will be modified to accommodate received points.
178620f4b53cSBarry Smith   If `remove_sent_points` is `PETSC_TRUE`, any points that were sent will be removed from the `DM`.
178720f4b53cSBarry Smith   Different styles of migration are supported. See `DMSwarmSetMigrateType()`.
178820f4b53cSBarry Smith 
178920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`
1790d3a51819SDave May @*/
1791d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points)
1792d71ae5a4SJacob Faibussowitsch {
1793f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1794f0cdbbbaSDave May 
1795521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0));
1797f0cdbbbaSDave May   switch (swarm->migrate_type) {
1798d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_BASIC:
1799d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points));
1800d71ae5a4SJacob Faibussowitsch     break;
1801d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLNSCATTER:
1802d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points));
1803d71ae5a4SJacob Faibussowitsch     break;
1804d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLEXACT:
1805d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1806d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_USER:
1807d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented");
1808d71ae5a4SJacob Faibussowitsch   default:
1809d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown");
1810f0cdbbbaSDave May   }
18119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0));
18129566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(dm));
18133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18143454631fSDave May }
18153454631fSDave May 
1816f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize);
1817f0cdbbbaSDave May 
1818d3a51819SDave May /*
1819d3a51819SDave May  DMSwarmCollectViewCreate
1820d3a51819SDave May 
1821d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1822d3a51819SDave May 
1823d3a51819SDave May  Notes:
18248b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1825d3a51819SDave May  they have finished computations associated with the collected points
1826d3a51819SDave May */
1827d3a51819SDave May 
182874d0cae8SMatthew G. Knepley /*@
1829d3a51819SDave May   DMSwarmCollectViewCreate - Applies a collection method and gathers points
183020f4b53cSBarry Smith   in neighbour ranks into the `DMSWARM`
1831d3a51819SDave May 
183220f4b53cSBarry Smith   Collective
1833d3a51819SDave May 
183460225df5SJacob Faibussowitsch   Input Parameter:
183520f4b53cSBarry Smith . dm - the `DMSWARM`
1836d3a51819SDave May 
1837d3a51819SDave May   Level: advanced
1838d3a51819SDave May 
183920f4b53cSBarry Smith   Notes:
184020f4b53cSBarry Smith   Users should call `DMSwarmCollectViewDestroy()` after
184120f4b53cSBarry Smith   they have finished computations associated with the collected points
18420764c050SBarry Smith 
184320f4b53cSBarry Smith   Different collect methods are supported. See `DMSwarmSetCollectType()`.
184420f4b53cSBarry Smith 
18450764c050SBarry Smith   Developer Note:
18460764c050SBarry Smith   Create and Destroy routines create new objects that can get destroyed, they do not change the state
18470764c050SBarry Smith   of the current object.
18480764c050SBarry Smith 
184920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()`
1850d3a51819SDave May @*/
1851d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewCreate(DM dm)
1852d71ae5a4SJacob Faibussowitsch {
18532712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
18542712d1f2SDave May   PetscInt  ng;
18552712d1f2SDave May 
1856521f74f9SMatthew G. Knepley   PetscFunctionBegin;
185728b400f6SJacob Faibussowitsch   PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active");
18589566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &ng));
1859480eef7bSDave May   switch (swarm->collect_type) {
1860d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_BASIC:
1861d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng));
1862d71ae5a4SJacob Faibussowitsch     break;
1863d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1864d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1865d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_GENERAL:
1866d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented");
1867d71ae5a4SJacob Faibussowitsch   default:
1868d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown");
1869480eef7bSDave May   }
1870480eef7bSDave May   swarm->collect_view_active       = PETSC_TRUE;
1871480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
18723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18732712d1f2SDave May }
18742712d1f2SDave May 
187574d0cae8SMatthew G. Knepley /*@
187620f4b53cSBarry Smith   DMSwarmCollectViewDestroy - Resets the `DMSWARM` to the size prior to calling `DMSwarmCollectViewCreate()`
1877d3a51819SDave May 
187820f4b53cSBarry Smith   Collective
1879d3a51819SDave May 
188060225df5SJacob Faibussowitsch   Input Parameters:
188120f4b53cSBarry Smith . dm - the `DMSWARM`
1882d3a51819SDave May 
1883d3a51819SDave May   Notes:
188420f4b53cSBarry Smith   Users should call `DMSwarmCollectViewCreate()` before this function is called.
1885d3a51819SDave May 
1886d3a51819SDave May   Level: advanced
1887d3a51819SDave May 
18880764c050SBarry Smith   Developer Note:
18890764c050SBarry Smith   Create and Destroy routines create new objects that can get destroyed, they do not change the state
18900764c050SBarry Smith   of the current object.
18910764c050SBarry Smith 
189220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()`
1893d3a51819SDave May @*/
1894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
1895d71ae5a4SJacob Faibussowitsch {
18962712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
18972712d1f2SDave May 
1898521f74f9SMatthew G. Knepley   PetscFunctionBegin;
189928b400f6SJacob Faibussowitsch   PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active");
19009566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1));
1901480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
19023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19032712d1f2SDave May }
19043454631fSDave May 
190566976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmSetUpPIC(DM dm)
1906d71ae5a4SJacob Faibussowitsch {
1907f0cdbbbaSDave May   PetscInt dim;
1908f0cdbbbaSDave May 
1909521f74f9SMatthew G. Knepley   PetscFunctionBegin;
19109566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetNumSpecies(dm, 1));
19119566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
191263a3b9bcSJacob Faibussowitsch   PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
191363a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
19143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1915f0cdbbbaSDave May }
1916f0cdbbbaSDave May 
191774d0cae8SMatthew G. Knepley /*@
191831403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
191931403186SMatthew G. Knepley 
192020f4b53cSBarry Smith   Collective
192131403186SMatthew G. Knepley 
192260225df5SJacob Faibussowitsch   Input Parameters:
192320f4b53cSBarry Smith + dm  - the `DMSWARM`
192420f4b53cSBarry Smith - Npc - The number of particles per cell in the cell `DM`
192531403186SMatthew G. Knepley 
192631403186SMatthew G. Knepley   Level: intermediate
192731403186SMatthew G. Knepley 
192820f4b53cSBarry Smith   Notes:
192920f4b53cSBarry Smith   The user must use `DMSwarmSetCellDM()` to set the cell `DM` first. The particles are placed randomly inside each cell. If only
193020f4b53cSBarry Smith   one particle is in each cell, it is placed at the centroid.
193120f4b53cSBarry Smith 
193220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`
193331403186SMatthew G. Knepley @*/
1934d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
1935d71ae5a4SJacob Faibussowitsch {
193631403186SMatthew G. Knepley   DM             cdm;
1937*19307e5cSMatthew G. Knepley   DMSwarmCellDM  celldm;
193831403186SMatthew G. Knepley   PetscRandom    rnd;
193931403186SMatthew G. Knepley   DMPolytopeType ct;
194031403186SMatthew G. Knepley   PetscBool      simplex;
194131403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
1942*19307e5cSMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p, Nfc;
1943*19307e5cSMatthew G. Knepley   const char   **coordFields;
194431403186SMatthew G. Knepley 
194531403186SMatthew G. Knepley   PetscFunctionBeginUser;
19469566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd));
19479566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0));
19489566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetType(rnd, PETSCRAND48));
194931403186SMatthew G. Knepley 
1950*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
1951*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
1952*19307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
19539566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
19549566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(cdm, &dim));
19559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd));
19569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(cdm, cStart, &ct));
195731403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
195831403186SMatthew G. Knepley 
19599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ));
196031403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
1961*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, coordFields[0], NULL, NULL, (void **)&coords));
196231403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
196331403186SMatthew G. Knepley     if (Npc == 1) {
19649566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL));
196531403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d];
196631403186SMatthew G. Knepley     } else {
19679566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */
196831403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
196931403186SMatthew G. Knepley         const PetscInt n   = c * Npc + p;
197031403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
197131403186SMatthew G. Knepley 
197231403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
19739566063dSJacob Faibussowitsch           PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d]));
197431403186SMatthew G. Knepley           sum += refcoords[d];
197531403186SMatthew G. Knepley         }
19769371c9d4SSatish Balay         if (simplex && sum > 0.0)
19779371c9d4SSatish Balay           for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum;
197831403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]);
197931403186SMatthew G. Knepley       }
198031403186SMatthew G. Knepley     }
198131403186SMatthew G. Knepley   }
1982*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, coordFields[0], NULL, NULL, (void **)&coords));
19839566063dSJacob Faibussowitsch   PetscCall(PetscFree5(centroid, xi0, v0, J, invJ));
19849566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rnd));
19853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
198631403186SMatthew G. Knepley }
198731403186SMatthew G. Knepley 
198831403186SMatthew G. Knepley /*@
198920f4b53cSBarry Smith   DMSwarmSetType - Set particular flavor of `DMSWARM`
1990d3a51819SDave May 
199120f4b53cSBarry Smith   Collective
1992d3a51819SDave May 
199360225df5SJacob Faibussowitsch   Input Parameters:
199420f4b53cSBarry Smith + dm    - the `DMSWARM`
199520f4b53cSBarry Smith - stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`)
1996d3a51819SDave May 
1997d3a51819SDave May   Level: advanced
1998d3a51819SDave May 
199920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC`
2000d3a51819SDave May @*/
2001d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetType(DM dm, DMSwarmType stype)
2002d71ae5a4SJacob Faibussowitsch {
2003f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2004f0cdbbbaSDave May 
2005521f74f9SMatthew G. Knepley   PetscFunctionBegin;
2006f0cdbbbaSDave May   swarm->swarm_type = stype;
200748a46eb9SPierre Jolivet   if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(dm));
20083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2009f0cdbbbaSDave May }
2010f0cdbbbaSDave May 
201166976f2fSJacob Faibussowitsch static PetscErrorCode DMSetup_Swarm(DM dm)
2012d71ae5a4SJacob Faibussowitsch {
20133454631fSDave May   DM_Swarm   *swarm = (DM_Swarm *)dm->data;
20143454631fSDave May   PetscMPIInt rank;
20153454631fSDave May   PetscInt    p, npoints, *rankval;
20163454631fSDave May 
2017521f74f9SMatthew G. Knepley   PetscFunctionBegin;
20183ba16761SJacob Faibussowitsch   if (swarm->issetup) PetscFunctionReturn(PETSC_SUCCESS);
20193454631fSDave May   swarm->issetup = PETSC_TRUE;
20203454631fSDave May 
2021f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
2022*19307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
2023f0cdbbbaSDave May 
2024*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
2025*19307e5cSMatthew G. Knepley     PetscCheck(celldm, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "No active cell DM. DMSWARM_PIC requires you call DMSwarmSetCellDM() or DMSwarmAddCellDM()");
2026*19307e5cSMatthew G. Knepley     if (celldm->dm->ops->locatepointssubdomain) {
2027f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
20289566063dSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n"));
2029f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
2030f0cdbbbaSDave May     } else {
2031f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
2032*19307e5cSMatthew G. Knepley       if (celldm->dm->ops->locatepoints) {
20339566063dSJacob Faibussowitsch         PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n"));
2034f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
2035f0cdbbbaSDave May 
2036*19307e5cSMatthew G. Knepley       if (celldm->dm->ops->getneighbors) {
20379566063dSJacob Faibussowitsch         PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n"));
2038f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
2039f0cdbbbaSDave May 
2040f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
2041f0cdbbbaSDave May     }
2042f0cdbbbaSDave May   }
2043f0cdbbbaSDave May 
20449566063dSJacob Faibussowitsch   PetscCall(DMSwarmFinalizeFieldRegister(dm));
2045f0cdbbbaSDave May 
20463454631fSDave May   /* check some fields were registered */
204708401ef6SPierre Jolivet   PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()");
20483454631fSDave May 
20493454631fSDave May   /* check local sizes were set */
205008401ef6SPierre Jolivet   PetscCheck(swarm->db->L != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Local sizes must be set via DMSwarmSetLocalSizes()");
20513454631fSDave May 
20523454631fSDave May   /* initialize values in pid and rank placeholders */
20533454631fSDave May   /* TODO: [pid - use MPI_Scan] */
20549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
20559566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL));
20569566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
2057835f2295SStefano Zampini   for (p = 0; p < npoints; p++) rankval[p] = rank;
20589566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
20593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20603454631fSDave May }
20613454631fSDave May 
206266976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroy_Swarm(DM dm)
2063d71ae5a4SJacob Faibussowitsch {
206457795646SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
206557795646SDave May 
206657795646SDave May   PetscFunctionBegin;
20673ba16761SJacob Faibussowitsch   if (--swarm->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
2068*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectListDestroy(&swarm->cellDMs));
2069*19307e5cSMatthew G. Knepley   PetscCall(PetscFree(swarm->activeCellDM));
20709566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&swarm->db));
20719566063dSJacob Faibussowitsch   PetscCall(PetscFree(swarm));
20723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207357795646SDave May }
207457795646SDave May 
207566976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
2076d71ae5a4SJacob Faibussowitsch {
2077a9ee3421SMatthew G. Knepley   DM            cdm;
2078*19307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
2079a9ee3421SMatthew G. Knepley   PetscDraw     draw;
208031403186SMatthew G. Knepley   PetscReal    *coords, oldPause, radius = 0.01;
2081*19307e5cSMatthew G. Knepley   PetscInt      Np, p, bs, Nfc;
2082*19307e5cSMatthew G. Knepley   const char  **coordFields;
2083a9ee3421SMatthew G. Knepley 
2084a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
20859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL));
20869566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
20879566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
20889566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetPause(draw, &oldPause));
20899566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, 0.0));
20909566063dSJacob Faibussowitsch   PetscCall(DMView(cdm, viewer));
20919566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, oldPause));
2092a9ee3421SMatthew G. Knepley 
2093*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
2094*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
2095*19307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
20969566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &Np));
2097*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, coordFields[0], &bs, NULL, (void **)&coords));
2098a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
2099a9ee3421SMatthew G. Knepley     const PetscInt i = p * bs;
2100a9ee3421SMatthew G. Knepley 
21019566063dSJacob Faibussowitsch     PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE));
2102a9ee3421SMatthew G. Knepley   }
2103*19307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, coordFields[0], &bs, NULL, (void **)&coords));
21049566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
21059566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
21069566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
21073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2108a9ee3421SMatthew G. Knepley }
2109a9ee3421SMatthew G. Knepley 
2110d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer)
2111d71ae5a4SJacob Faibussowitsch {
21126a5217c0SMatthew G. Knepley   PetscViewerFormat format;
21136a5217c0SMatthew G. Knepley   PetscInt         *sizes;
21146a5217c0SMatthew G. Knepley   PetscInt          dim, Np, maxSize = 17;
21156a5217c0SMatthew G. Knepley   MPI_Comm          comm;
21166a5217c0SMatthew G. Knepley   PetscMPIInt       rank, size, p;
2117*19307e5cSMatthew G. Knepley   const char       *name, *cellid;
21186a5217c0SMatthew G. Knepley 
21196a5217c0SMatthew G. Knepley   PetscFunctionBegin;
21206a5217c0SMatthew G. Knepley   PetscCall(PetscViewerGetFormat(viewer, &format));
21216a5217c0SMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
21226a5217c0SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dm, &Np));
21236a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
21246a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
21256a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
21266a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
212763a3b9bcSJacob Faibussowitsch   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
212863a3b9bcSJacob Faibussowitsch   else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
21296a5217c0SMatthew G. Knepley   if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes));
21306a5217c0SMatthew G. Knepley   else PetscCall(PetscCalloc1(3, &sizes));
21316a5217c0SMatthew G. Knepley   if (size < maxSize) {
21326a5217c0SMatthew G. Knepley     PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
21336a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of particles per rank:"));
21346a5217c0SMatthew G. Knepley     for (p = 0; p < size; ++p) {
21356a5217c0SMatthew G. Knepley       if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]));
21366a5217c0SMatthew G. Knepley     }
21376a5217c0SMatthew G. Knepley   } else {
21386a5217c0SMatthew G. Knepley     PetscInt locMinMax[2] = {Np, Np};
21396a5217c0SMatthew G. Knepley 
21406a5217c0SMatthew G. Knepley     PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
21416a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
21426a5217c0SMatthew G. Knepley   }
21436a5217c0SMatthew G. Knepley   PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
21446a5217c0SMatthew G. Knepley   PetscCall(PetscFree(sizes));
21456a5217c0SMatthew G. Knepley   if (format == PETSC_VIEWER_ASCII_INFO) {
2146*19307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
21476a5217c0SMatthew G. Knepley     PetscInt     *cell;
21486a5217c0SMatthew G. Knepley 
21496a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells containing each particle:\n"));
21506a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
2151*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
2152*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMGetCellID(celldm, &cellid));
2153*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&cell));
215463a3b9bcSJacob Faibussowitsch     for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  p%d: %" PetscInt_FMT "\n", p, cell[p]));
21556a5217c0SMatthew G. Knepley     PetscCall(PetscViewerFlush(viewer));
21566a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
2157*19307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&cell));
21586a5217c0SMatthew G. Knepley   }
21593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21606a5217c0SMatthew G. Knepley }
21616a5217c0SMatthew G. Knepley 
216266976f2fSJacob Faibussowitsch static PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
2163d71ae5a4SJacob Faibussowitsch {
21645f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
21654fc69c0aSMatthew G. Knepley   PetscBool iascii, ibinary, isvtk, isdraw, ispython;
21665627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
21675627991aSBarry Smith   PetscBool ishdf5;
21685627991aSBarry Smith #endif
21695f50eb2eSDave May 
21705f50eb2eSDave May   PetscFunctionBegin;
21715f50eb2eSDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21725f50eb2eSDave May   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
21749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
21759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
21765627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
21779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21785627991aSBarry Smith #endif
21799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
21804fc69c0aSMatthew G. Knepley   PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython));
21815f50eb2eSDave May   if (iascii) {
21826a5217c0SMatthew G. Knepley     PetscViewerFormat format;
21836a5217c0SMatthew G. Knepley 
21846a5217c0SMatthew G. Knepley     PetscCall(PetscViewerGetFormat(viewer, &format));
21856a5217c0SMatthew G. Knepley     switch (format) {
2186d71ae5a4SJacob Faibussowitsch     case PETSC_VIEWER_ASCII_INFO_DETAIL:
2187d71ae5a4SJacob Faibussowitsch       PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT));
2188d71ae5a4SJacob Faibussowitsch       break;
2189d71ae5a4SJacob Faibussowitsch     default:
2190d71ae5a4SJacob Faibussowitsch       PetscCall(DMView_Swarm_Ascii(dm, viewer));
21916a5217c0SMatthew G. Knepley     }
2192f7d195e4SLawrence Mitchell   } else {
21935f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
219448a46eb9SPierre Jolivet     if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer));
21955f50eb2eSDave May #endif
219648a46eb9SPierre Jolivet     if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer));
21974fc69c0aSMatthew G. Knepley     if (ispython) PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)dm));
2198f7d195e4SLawrence Mitchell   }
21993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22005f50eb2eSDave May }
22015f50eb2eSDave May 
2202cc4c1da9SBarry Smith /*@
220320f4b53cSBarry Smith   DMSwarmGetCellSwarm - Extracts a single cell from the `DMSWARM` object, returns it as a single cell `DMSWARM`.
220420f4b53cSBarry Smith   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.
2205d0c080abSJoseph Pusztay 
2206d0c080abSJoseph Pusztay   Noncollective
2207d0c080abSJoseph Pusztay 
220860225df5SJacob Faibussowitsch   Input Parameters:
220920f4b53cSBarry Smith + sw        - the `DMSWARM`
22105627991aSBarry Smith . cellID    - the integer id of the cell to be extracted and filtered
221120f4b53cSBarry Smith - cellswarm - The `DMSWARM` to receive the cell
2212d0c080abSJoseph Pusztay 
2213d0c080abSJoseph Pusztay   Level: beginner
2214d0c080abSJoseph Pusztay 
22155627991aSBarry Smith   Notes:
221620f4b53cSBarry Smith   This presently only supports `DMSWARM_PIC` type
22175627991aSBarry Smith 
221820f4b53cSBarry Smith   Should be restored with `DMSwarmRestoreCellSwarm()`
2219d0c080abSJoseph Pusztay 
222020f4b53cSBarry Smith   Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
222120f4b53cSBarry Smith 
222220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreCellSwarm()`
2223d0c080abSJoseph Pusztay @*/
2224cc4c1da9SBarry Smith PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
2225d71ae5a4SJacob Faibussowitsch {
2226d0c080abSJoseph Pusztay   DM_Swarm   *original = (DM_Swarm *)sw->data;
2227d0c080abSJoseph Pusztay   DMLabel     label;
2228d0c080abSJoseph Pusztay   DM          dmc, subdmc;
2229d0c080abSJoseph Pusztay   PetscInt   *pids, particles, dim;
2230*19307e5cSMatthew G. Knepley   const char *name;
2231d0c080abSJoseph Pusztay 
2232d0c080abSJoseph Pusztay   PetscFunctionBegin;
2233d0c080abSJoseph Pusztay   /* Configure new swarm */
22349566063dSJacob Faibussowitsch   PetscCall(DMSetType(cellswarm, DMSWARM));
22359566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(sw, &dim));
22369566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(cellswarm, dim));
22379566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC));
2238d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
22399566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db));
22409566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
22419566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles));
22429566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
22439566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db));
22449566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
2245fe11354eSMatthew G. Knepley   PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids));
22469566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(sw, &dmc));
22479566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label));
22489566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(dmc, label));
22499566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cellID, 1));
225030cbcd5dSksagiyam   PetscCall(DMPlexFilter(dmc, label, 1, PETSC_FALSE, PETSC_FALSE, NULL, &subdmc));
2251*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dmc, &name));
2252*19307e5cSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)subdmc, name));
22539566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetCellDM(cellswarm, subdmc));
22549566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
22553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2256d0c080abSJoseph Pusztay }
2257d0c080abSJoseph Pusztay 
2258cc4c1da9SBarry Smith /*@
225920f4b53cSBarry Smith   DMSwarmRestoreCellSwarm - Restores a `DMSWARM` object obtained with `DMSwarmGetCellSwarm()`. All fields are copied back into the parent swarm.
2260d0c080abSJoseph Pusztay 
2261d0c080abSJoseph Pusztay   Noncollective
2262d0c080abSJoseph Pusztay 
226360225df5SJacob Faibussowitsch   Input Parameters:
226420f4b53cSBarry Smith + sw        - the parent `DMSWARM`
2265d0c080abSJoseph Pusztay . cellID    - the integer id of the cell to be copied back into the parent swarm
2266d0c080abSJoseph Pusztay - cellswarm - the cell swarm object
2267d0c080abSJoseph Pusztay 
2268d0c080abSJoseph Pusztay   Level: beginner
2269d0c080abSJoseph Pusztay 
22705627991aSBarry Smith   Note:
227120f4b53cSBarry Smith   This only supports `DMSWARM_PIC` types of `DMSWARM`s
2272d0c080abSJoseph Pusztay 
227320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetCellSwarm()`
2274d0c080abSJoseph Pusztay @*/
2275cc4c1da9SBarry Smith PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
2276d71ae5a4SJacob Faibussowitsch {
2277d0c080abSJoseph Pusztay   DM        dmc;
2278d0c080abSJoseph Pusztay   PetscInt *pids, particles, p;
2279d0c080abSJoseph Pusztay 
2280d0c080abSJoseph Pusztay   PetscFunctionBegin;
22819566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
22829566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
22839566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
2284d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
228548a46eb9SPierre Jolivet   for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p]));
2286d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
22879566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(cellswarm, &dmc));
22889566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
2289fe11354eSMatthew G. Knepley   PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids));
22903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2291d0c080abSJoseph Pusztay }
2292d0c080abSJoseph Pusztay 
2293d52c2f21SMatthew G. Knepley /*@
2294d52c2f21SMatthew G. Knepley   DMSwarmComputeMoments - Compute the first three particle moments for a given field
2295d52c2f21SMatthew G. Knepley 
2296d52c2f21SMatthew G. Knepley   Noncollective
2297d52c2f21SMatthew G. Knepley 
2298d52c2f21SMatthew G. Knepley   Input Parameters:
2299d52c2f21SMatthew G. Knepley + sw         - the `DMSWARM`
2300d52c2f21SMatthew G. Knepley . coordinate - the coordinate field name
2301d52c2f21SMatthew G. Knepley - weight     - the weight field name
2302d52c2f21SMatthew G. Knepley 
2303d52c2f21SMatthew G. Knepley   Output Parameter:
2304d52c2f21SMatthew G. Knepley . moments - the field moments
2305d52c2f21SMatthew G. Knepley 
2306d52c2f21SMatthew G. Knepley   Level: intermediate
2307d52c2f21SMatthew G. Knepley 
2308d52c2f21SMatthew G. Knepley   Notes:
2309d52c2f21SMatthew G. Knepley   The `moments` array should be of length bs + 2, where bs is the block size of the coordinate field.
2310d52c2f21SMatthew G. Knepley 
2311d52c2f21SMatthew G. Knepley   The weight field must be a scalar, having blocksize 1.
2312d52c2f21SMatthew G. Knepley 
2313d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMPlexComputeMoments()`
2314d52c2f21SMatthew G. Knepley @*/
2315d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmComputeMoments(DM sw, const char coordinate[], const char weight[], PetscReal moments[])
2316d52c2f21SMatthew G. Knepley {
2317d52c2f21SMatthew G. Knepley   const PetscReal *coords;
2318d52c2f21SMatthew G. Knepley   const PetscReal *w;
2319d52c2f21SMatthew G. Knepley   PetscReal       *mom;
2320d52c2f21SMatthew G. Knepley   PetscDataType    dtc, dtw;
2321d52c2f21SMatthew G. Knepley   PetscInt         bsc, bsw, Np;
2322d52c2f21SMatthew G. Knepley   MPI_Comm         comm;
2323d52c2f21SMatthew G. Knepley 
2324d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
2325d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
2326d52c2f21SMatthew G. Knepley   PetscAssertPointer(coordinate, 2);
2327d52c2f21SMatthew G. Knepley   PetscAssertPointer(weight, 3);
2328d52c2f21SMatthew G. Knepley   PetscAssertPointer(moments, 4);
2329d52c2f21SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
2330d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, coordinate, &bsc, &dtc, (void **)&coords));
2331d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, weight, &bsw, &dtw, (void **)&w));
2332d52c2f21SMatthew G. Knepley   PetscCheck(dtc == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s must be real, not %s", coordinate, PetscDataTypes[dtc]);
2333d52c2f21SMatthew G. Knepley   PetscCheck(dtw == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be real, not %s", weight, PetscDataTypes[dtw]);
2334d52c2f21SMatthew G. Knepley   PetscCheck(bsw == 1, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be a scalar, not blocksize %" PetscInt_FMT, weight, bsw);
2335d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(sw, &Np));
2336d52c2f21SMatthew G. Knepley   PetscCall(DMGetWorkArray(sw, bsc + 2, MPIU_REAL, &mom));
2337d52c2f21SMatthew G. Knepley   PetscCall(PetscArrayzero(mom, bsc + 2));
2338d52c2f21SMatthew G. Knepley   for (PetscInt p = 0; p < Np; ++p) {
2339d52c2f21SMatthew G. Knepley     const PetscReal *c  = &coords[p * bsc];
2340d52c2f21SMatthew G. Knepley     const PetscReal  wp = w[p];
2341d52c2f21SMatthew G. Knepley 
2342d52c2f21SMatthew G. Knepley     mom[0] += wp;
2343d52c2f21SMatthew G. Knepley     for (PetscInt d = 0; d < bsc; ++d) {
2344d52c2f21SMatthew G. Knepley       mom[d + 1] += wp * c[d];
2345d52c2f21SMatthew G. Knepley       mom[d + bsc + 1] += wp * PetscSqr(c[d]);
2346d52c2f21SMatthew G. Knepley     }
2347d52c2f21SMatthew G. Knepley   }
2348d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&coords));
2349d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w));
2350d52c2f21SMatthew G. Knepley   PetscCallMPI(MPIU_Allreduce(mom, moments, bsc + 2, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)sw)));
2351d52c2f21SMatthew G. Knepley   PetscCall(DMRestoreWorkArray(sw, bsc + 2, MPIU_REAL, &mom));
2352d0c080abSJoseph Pusztay   PetscFunctionReturn(PETSC_SUCCESS);
2353d0c080abSJoseph Pusztay }
2354d0c080abSJoseph Pusztay 
2355d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
2356d0c080abSJoseph Pusztay 
2357d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Swarm(DM sw)
2358d71ae5a4SJacob Faibussowitsch {
2359d0c080abSJoseph Pusztay   PetscFunctionBegin;
2360d0c080abSJoseph Pusztay   sw->ops->view                     = DMView_Swarm;
2361d0c080abSJoseph Pusztay   sw->ops->load                     = NULL;
2362d0c080abSJoseph Pusztay   sw->ops->setfromoptions           = NULL;
2363d0c080abSJoseph Pusztay   sw->ops->clone                    = DMClone_Swarm;
2364d0c080abSJoseph Pusztay   sw->ops->setup                    = DMSetup_Swarm;
2365d0c080abSJoseph Pusztay   sw->ops->createlocalsection       = NULL;
2366adc21957SMatthew G. Knepley   sw->ops->createsectionpermutation = NULL;
2367d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints = NULL;
2368d0c080abSJoseph Pusztay   sw->ops->createglobalvector       = DMCreateGlobalVector_Swarm;
2369d0c080abSJoseph Pusztay   sw->ops->createlocalvector        = DMCreateLocalVector_Swarm;
2370d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping  = NULL;
2371d0c080abSJoseph Pusztay   sw->ops->createfieldis            = NULL;
2372d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm       = NULL;
2373d0c080abSJoseph Pusztay   sw->ops->getcoloring              = NULL;
2374d0c080abSJoseph Pusztay   sw->ops->creatematrix             = DMCreateMatrix_Swarm;
2375d0c080abSJoseph Pusztay   sw->ops->createinterpolation      = NULL;
2376d0c080abSJoseph Pusztay   sw->ops->createinjection          = NULL;
2377d0c080abSJoseph Pusztay   sw->ops->createmassmatrix         = DMCreateMassMatrix_Swarm;
2378d0c080abSJoseph Pusztay   sw->ops->refine                   = NULL;
2379d0c080abSJoseph Pusztay   sw->ops->coarsen                  = NULL;
2380d0c080abSJoseph Pusztay   sw->ops->refinehierarchy          = NULL;
2381d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy         = NULL;
2382d0c080abSJoseph Pusztay   sw->ops->globaltolocalbegin       = NULL;
2383d0c080abSJoseph Pusztay   sw->ops->globaltolocalend         = NULL;
2384d0c080abSJoseph Pusztay   sw->ops->localtoglobalbegin       = NULL;
2385d0c080abSJoseph Pusztay   sw->ops->localtoglobalend         = NULL;
2386d0c080abSJoseph Pusztay   sw->ops->destroy                  = DMDestroy_Swarm;
2387d0c080abSJoseph Pusztay   sw->ops->createsubdm              = NULL;
2388d0c080abSJoseph Pusztay   sw->ops->getdimpoints             = NULL;
2389d0c080abSJoseph Pusztay   sw->ops->locatepoints             = NULL;
23903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2391d0c080abSJoseph Pusztay }
2392d0c080abSJoseph Pusztay 
2393d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm)
2394d71ae5a4SJacob Faibussowitsch {
2395d0c080abSJoseph Pusztay   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2396d0c080abSJoseph Pusztay 
2397d0c080abSJoseph Pusztay   PetscFunctionBegin;
2398d0c080abSJoseph Pusztay   swarm->refct++;
2399d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
24009566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM));
24019566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(*newdm));
24022e56dffeSJoe Pusztay   (*newdm)->dim = dm->dim;
24033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2404d0c080abSJoseph Pusztay }
2405d0c080abSJoseph Pusztay 
2406d3a51819SDave May /*MC
240720f4b53cSBarry Smith  DMSWARM = "swarm" - A `DM` object used to represent arrays of data (fields) of arbitrary data type.
240862741f57SDave May  This implementation was designed for particle methods in which the underlying
2409d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
2410d3a51819SDave May 
241120f4b53cSBarry Smith  Level: intermediate
241220f4b53cSBarry Smith 
241320f4b53cSBarry Smith   Notes:
241420f4b53cSBarry Smith  User data can be represented by `DMSWARM` through a registering "fields".
241562741f57SDave May  To register a field, the user must provide;
241662741f57SDave May  (a) a unique name;
241762741f57SDave May  (b) the data type (or size in bytes);
241862741f57SDave May  (c) the block size of the data.
2419d3a51819SDave May 
2420d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
2421c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
242220f4b53cSBarry Smith .vb
242320f4b53cSBarry Smith     DMSwarmInitializeFieldRegister(dm)
242420f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
242520f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
242620f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
242720f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
242820f4b53cSBarry Smith     DMSwarmFinalizeFieldRegister(dm)
242920f4b53cSBarry Smith .ve
2430d3a51819SDave May 
243120f4b53cSBarry Smith  The fields represented by `DMSWARM` are dynamic and can be re-sized at any time.
243220f4b53cSBarry Smith  The only restriction imposed by `DMSWARM` is that all fields contain the same number of points.
2433d3a51819SDave May 
2434d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
24355627991aSBarry Smith  between ranks.
2436d3a51819SDave May 
243720f4b53cSBarry Smith  `DMSWARM` supports the methods `DMCreateGlobalVector()` and `DMCreateLocalVector()`.
243820f4b53cSBarry Smith  As a `DMSWARM` may internally define and store values of different data types,
243920f4b53cSBarry Smith  before calling `DMCreateGlobalVector()` or `DMCreateLocalVector()`, the user must inform `DMSWARM` which
244020f4b53cSBarry Smith  fields should be used to define a `Vec` object via
244120f4b53cSBarry Smith    `DMSwarmVectorDefineField()`
2442c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
2443c215a47eSMatthew Knepley  compatible with different fields to be created.
2444d3a51819SDave May 
244520f4b53cSBarry Smith  A dual representation of fields in the `DMSWARM` and a Vec object is permitted via
244620f4b53cSBarry Smith    `DMSwarmCreateGlobalVectorFromField()`
244720f4b53cSBarry Smith  Here the data defining the field in the `DMSWARM` is shared with a Vec.
2448d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
244920f4b53cSBarry Smith  calls to `DMSwarmCreateGlobalVectorFromField()` and `DMSwarmDestroyGlobalVectorFromField()`.
245020f4b53cSBarry Smith  If the local size of the `DMSWARM` does not match the local size of the global vector
245120f4b53cSBarry Smith  when `DMSwarmDestroyGlobalVectorFromField()` is called, an error is thrown.
2452d3a51819SDave May 
245362741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
245420f4b53cSBarry Smith  Please refer to `DMSwarmSetType()`.
245562741f57SDave May 
245620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMType`, `DMCreate()`, `DMSetType()`
2457d3a51819SDave May M*/
2458cc4c1da9SBarry Smith 
2459d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
2460d71ae5a4SJacob Faibussowitsch {
246157795646SDave May   DM_Swarm *swarm;
246257795646SDave May 
246357795646SDave May   PetscFunctionBegin;
246457795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24654dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&swarm));
2466f0cdbbbaSDave May   dm->data = swarm;
24679566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreate(&swarm->db));
24689566063dSJacob Faibussowitsch   PetscCall(DMSwarmInitializeFieldRegister(dm));
2469d52c2f21SMatthew G. Knepley   dm->dim                               = 0;
2470d0c080abSJoseph Pusztay   swarm->refct                          = 1;
24713454631fSDave May   swarm->issetup                        = PETSC_FALSE;
2472480eef7bSDave May   swarm->swarm_type                     = DMSWARM_BASIC;
2473480eef7bSDave May   swarm->migrate_type                   = DMSWARM_MIGRATE_BASIC;
2474480eef7bSDave May   swarm->collect_type                   = DMSWARM_COLLECT_BASIC;
247540c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
2476f0cdbbbaSDave May   swarm->collect_view_active            = PETSC_FALSE;
2477f0cdbbbaSDave May   swarm->collect_view_reset_nlocal      = -1;
24789566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(dm));
24792e956fe4SStefano Zampini   if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId));
24803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
248157795646SDave May }
2482*19307e5cSMatthew G. Knepley 
2483*19307e5cSMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
2484*19307e5cSMatthew G. Knepley    - Share the DM_Swarm structure
2485*19307e5cSMatthew G. Knepley */
2486*19307e5cSMatthew G. Knepley PetscErrorCode DMSwarmReplace(DM dm, DM *ndm)
2487*19307e5cSMatthew G. Knepley {
2488*19307e5cSMatthew G. Knepley   DM               dmNew = *ndm;
2489*19307e5cSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
2490*19307e5cSMatthew G. Knepley   PetscInt         dim;
2491*19307e5cSMatthew G. Knepley 
2492*19307e5cSMatthew G. Knepley   PetscFunctionBegin;
2493*19307e5cSMatthew G. Knepley   if (dm == dmNew) {
2494*19307e5cSMatthew G. Knepley     PetscCall(DMDestroy(ndm));
2495*19307e5cSMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
2496*19307e5cSMatthew G. Knepley   }
2497*19307e5cSMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
2498*19307e5cSMatthew G. Knepley   if (!dm->hdr.name) {
2499*19307e5cSMatthew G. Knepley     const char *name;
2500*19307e5cSMatthew G. Knepley 
2501*19307e5cSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)*ndm, &name));
2502*19307e5cSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
2503*19307e5cSMatthew G. Knepley   }
2504*19307e5cSMatthew G. Knepley   PetscCall(DMGetDimension(dmNew, &dim));
2505*19307e5cSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
2506*19307e5cSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
2507*19307e5cSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
2508*19307e5cSMatthew G. Knepley   PetscCall(DMDestroy_Swarm(dm));
2509*19307e5cSMatthew G. Knepley   PetscCall(DMInitialize_Swarm(dm));
2510*19307e5cSMatthew G. Knepley   dm->data = dmNew->data;
2511*19307e5cSMatthew G. Knepley   ((DM_Swarm *)dmNew->data)->refct++;
2512*19307e5cSMatthew G. Knepley   PetscCall(DMDestroy(ndm));
2513*19307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2514*19307e5cSMatthew G. Knepley }
2515