xref: /petsc/src/dm/impls/swarm/swarm.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
119307e5cSMatthew G. Knepley #include "petscdmswarm.h"
257795646SDave May #include <petsc/private/dmswarmimpl.h> /*I   "petscdmswarm.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
40643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>
55917a6f0SStefano Zampini #include <petscviewer.h>
65917a6f0SStefano Zampini #include <petscdraw.h>
783c47955SMatthew G. Knepley #include <petscdmplex.h>
84cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h>
9279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
10d0c080abSJoseph Pusztay #include <petscdmlabel.h>
11d0c080abSJoseph Pusztay #include <petscsection.h>
1257795646SDave May 
13f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
14ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
15ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
16ed923d71SDave May 
17ea78f98cSLisandro Dalcin const char *DMSwarmTypeNames[]          = {"basic", "pic", NULL};
18ea78f98cSLisandro Dalcin const char *DMSwarmMigrateTypeNames[]   = {"basic", "dmcellnscatter", "dmcellexact", "user", NULL};
19ea78f98cSLisandro Dalcin const char *DMSwarmCollectTypeNames[]   = {"basic", "boundingbox", "general", "user", NULL};
20fca3fa51SMatthew G. Knepley const char *DMSwarmRemapTypeNames[]     = {"none", "pfak", "colella", "DMSwarmRemapType", "DMSWARM_REMAP_", NULL};
21ea78f98cSLisandro Dalcin const char *DMSwarmPICLayoutTypeNames[] = {"regular", "gauss", "subdivision", NULL};
22f0cdbbbaSDave May 
23f0cdbbbaSDave May const char DMSwarmField_pid[]     = "DMSwarm_pid";
24f0cdbbbaSDave May const char DMSwarmField_rank[]    = "DMSwarm_rank";
25f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
26f0cdbbbaSDave May 
272e956fe4SStefano Zampini PetscInt SwarmDataFieldId = -1;
282e956fe4SStefano Zampini 
2974d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
3074d0cae8SMatthew G. Knepley   #include <petscviewerhdf5.h>
3174d0cae8SMatthew G. Knepley 
VecView_Swarm_HDF5_Internal(Vec v,PetscViewer viewer)3266976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer)
33d71ae5a4SJacob Faibussowitsch {
3474d0cae8SMatthew G. Knepley   DM        dm;
3574d0cae8SMatthew G. Knepley   PetscReal seqval;
3674d0cae8SMatthew G. Knepley   PetscInt  seqnum, bs;
37eb0c6899SMatthew G. Knepley   PetscBool isseq, ists;
3874d0cae8SMatthew G. Knepley 
3974d0cae8SMatthew G. Knepley   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
419566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(v, &bs));
429566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields"));
439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
449566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval));
45eb0c6899SMatthew G. Knepley   PetscCall(PetscViewerHDF5IsTimestepping(viewer, &ists));
46eb0c6899SMatthew G. Knepley   if (ists) PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
479566063dSJacob Faibussowitsch   /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */
489566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
499566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs));
509566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5274d0cae8SMatthew G. Knepley }
5374d0cae8SMatthew G. Knepley 
DMSwarmView_HDF5(DM dm,PetscViewer viewer)5466976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer)
55d71ae5a4SJacob Faibussowitsch {
5619307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
5774d0cae8SMatthew G. Knepley   Vec           coordinates;
5819307e5cSMatthew G. Knepley   PetscInt      Np, Nfc;
5974d0cae8SMatthew G. Knepley   PetscBool     isseq;
6019307e5cSMatthew G. Knepley   const char  **coordFields;
6174d0cae8SMatthew G. Knepley 
6274d0cae8SMatthew G. Knepley   PetscFunctionBegin;
6319307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
6419307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
6519307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
669566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetSize(dm, &Np));
6719307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateGlobalVectorFromField(dm, coordFields[0], &coordinates));
689566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
699566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles"));
709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq));
719566063dSJacob Faibussowitsch   PetscCall(VecViewNative(coordinates, viewer));
729566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np));
739566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
7419307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, coordFields[0], &coordinates));
753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7674d0cae8SMatthew G. Knepley }
7774d0cae8SMatthew G. Knepley #endif
7874d0cae8SMatthew G. Knepley 
VecView_Swarm(Vec v,PetscViewer viewer)7966976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer)
80d71ae5a4SJacob Faibussowitsch {
8174d0cae8SMatthew G. Knepley   DM dm;
82f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
8374d0cae8SMatthew G. Knepley   PetscBool ishdf5;
84f9558f5cSBarry Smith #endif
8574d0cae8SMatthew G. Knepley 
8674d0cae8SMatthew G. Knepley   PetscFunctionBegin;
879566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
8828b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
89f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
9174d0cae8SMatthew G. Knepley   if (ishdf5) {
929566063dSJacob Faibussowitsch     PetscCall(VecView_Swarm_HDF5_Internal(v, viewer));
933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9474d0cae8SMatthew G. Knepley   }
95f9558f5cSBarry Smith #endif
969566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9874d0cae8SMatthew G. Knepley }
9974d0cae8SMatthew G. Knepley 
100d52c2f21SMatthew G. Knepley /*@C
101d52c2f21SMatthew G. Knepley   DMSwarmVectorGetField - Gets the fields from which to define a `Vec` object
1020bf7c1c5SMatthew G. Knepley   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
1030bf7c1c5SMatthew G. Knepley 
1040bf7c1c5SMatthew G. Knepley   Not collective
1050bf7c1c5SMatthew G. Knepley 
1060bf7c1c5SMatthew G. Knepley   Input Parameter:
10719307e5cSMatthew G. Knepley . sw - a `DMSWARM`
1080bf7c1c5SMatthew G. Knepley 
109d52c2f21SMatthew G. Knepley   Output Parameters:
110d52c2f21SMatthew G. Knepley + Nf         - the number of fields
111d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field, or NULL if it has not been set
1120bf7c1c5SMatthew G. Knepley 
1130bf7c1c5SMatthew G. Knepley   Level: beginner
1140bf7c1c5SMatthew G. Knepley 
115d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
1160bf7c1c5SMatthew G. Knepley @*/
DMSwarmVectorGetField(DM sw,PetscInt * Nf,const char ** fieldnames[])11719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorGetField(DM sw, PetscInt *Nf, const char **fieldnames[])
1180bf7c1c5SMatthew G. Knepley {
11919307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
12019307e5cSMatthew G. Knepley 
1210bf7c1c5SMatthew G. Knepley   PetscFunctionBegin;
12219307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM);
12319307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
12419307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetFields(celldm, Nf, fieldnames));
1250bf7c1c5SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1260bf7c1c5SMatthew G. Knepley }
1270bf7c1c5SMatthew G. Knepley 
128cc4c1da9SBarry Smith /*@
12920f4b53cSBarry Smith   DMSwarmVectorDefineField - Sets the field from which to define a `Vec` object
13020f4b53cSBarry Smith   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
13157795646SDave May 
13220f4b53cSBarry Smith   Collective
13357795646SDave May 
13460225df5SJacob Faibussowitsch   Input Parameters:
13520f4b53cSBarry Smith + dm        - a `DMSWARM`
136d52c2f21SMatthew G. Knepley - fieldname - the textual name given to each registered field
13757795646SDave May 
138d3a51819SDave May   Level: beginner
13957795646SDave May 
140d3a51819SDave May   Notes:
14120f4b53cSBarry Smith   The field with name `fieldname` must be defined as having a data type of `PetscScalar`.
142e7af74c8SDave May 
14320f4b53cSBarry Smith   This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`.
14420f4b53cSBarry Smith   Multiple calls to `DMSwarmVectorDefineField()` are permitted.
145e7af74c8SDave May 
146d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineFields()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
147d3a51819SDave May @*/
DMSwarmVectorDefineField(DM dm,const char fieldname[])148d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[])
149d71ae5a4SJacob Faibussowitsch {
150d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
151d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmVectorDefineFields(dm, 1, &fieldname));
152d52c2f21SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
153d52c2f21SMatthew G. Knepley }
154d52c2f21SMatthew G. Knepley 
155d52c2f21SMatthew G. Knepley /*@C
156d52c2f21SMatthew G. Knepley   DMSwarmVectorDefineFields - Sets the fields from which to define a `Vec` object
157d52c2f21SMatthew G. Knepley   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
158d52c2f21SMatthew G. Knepley 
159d52c2f21SMatthew G. Knepley   Collective, No Fortran support
160d52c2f21SMatthew G. Knepley 
161d52c2f21SMatthew G. Knepley   Input Parameters:
16219307e5cSMatthew G. Knepley + sw         - a `DMSWARM`
163d52c2f21SMatthew G. Knepley . Nf         - the number of fields
164d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field
165d52c2f21SMatthew G. Knepley 
166d52c2f21SMatthew G. Knepley   Level: beginner
167d52c2f21SMatthew G. Knepley 
168d52c2f21SMatthew G. Knepley   Notes:
169d52c2f21SMatthew G. Knepley   Each field with name in `fieldnames` must be defined as having a data type of `PetscScalar`.
170d52c2f21SMatthew G. Knepley 
171d52c2f21SMatthew G. Knepley   This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`.
172d52c2f21SMatthew G. Knepley   Multiple calls to `DMSwarmVectorDefineField()` are permitted.
173d52c2f21SMatthew G. Knepley 
174d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
175d52c2f21SMatthew G. Knepley @*/
DMSwarmVectorDefineFields(DM sw,PetscInt Nf,const char * fieldnames[])17619307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineFields(DM sw, PetscInt Nf, const char *fieldnames[])
177d52c2f21SMatthew G. Knepley {
17819307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
17919307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
180b5bcf523SDave May 
181a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
18219307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM);
183d52c2f21SMatthew G. Knepley   if (fieldnames) PetscAssertPointer(fieldnames, 3);
18419307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
18519307e5cSMatthew G. Knepley   PetscCheck(Nf >= 0, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields must be non-negative, not %" PetscInt_FMT, Nf);
18619307e5cSMatthew G. Knepley   // Create a dummy cell DM if none has been specified (I think we should not support this mode)
18719307e5cSMatthew G. Knepley   if (!swarm->activeCellDM) {
18819307e5cSMatthew G. Knepley     DM            dm;
18919307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
190b5bcf523SDave May 
19119307e5cSMatthew G. Knepley     PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), &dm));
19219307e5cSMatthew G. Knepley     PetscCall(DMSetType(dm, DMSHELL));
19319307e5cSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, "dummy"));
19419307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 0, NULL, &celldm));
19519307e5cSMatthew G. Knepley     PetscCall(DMDestroy(&dm));
19619307e5cSMatthew G. Knepley     PetscCall(DMSwarmAddCellDM(sw, celldm));
19719307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMDestroy(&celldm));
19819307e5cSMatthew G. Knepley     PetscCall(DMSwarmSetCellDMActive(sw, "dummy"));
19919307e5cSMatthew G. Knepley   }
20019307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
20119307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) PetscCall(PetscFree(celldm->dmFields[f]));
20219307e5cSMatthew G. Knepley   PetscCall(PetscFree(celldm->dmFields));
20319307e5cSMatthew G. Knepley 
20419307e5cSMatthew G. Knepley   celldm->Nf = Nf;
20519307e5cSMatthew G. Knepley   PetscCall(PetscMalloc1(Nf, &celldm->dmFields));
206d52c2f21SMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
207d52c2f21SMatthew G. Knepley     PetscDataType type;
208d52c2f21SMatthew G. Knepley 
209d52c2f21SMatthew G. Knepley     // Check all fields are of type PETSC_REAL or PETSC_SCALAR
21019307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], NULL, &type));
21119307e5cSMatthew G. Knepley     PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
21219307e5cSMatthew G. Knepley     PetscCall(PetscStrallocpy(fieldnames[f], (char **)&celldm->dmFields[f]));
213d52c2f21SMatthew G. Knepley   }
2143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
215b5bcf523SDave May }
216b5bcf523SDave May 
217cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
DMCreateGlobalVector_Swarm(DM sw,Vec * vec)21819307e5cSMatthew G. Knepley static PetscErrorCode DMCreateGlobalVector_Swarm(DM sw, Vec *vec)
219d71ae5a4SJacob Faibussowitsch {
22019307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
22119307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
222b5bcf523SDave May   Vec           x;
223b5bcf523SDave May   char          name[PETSC_MAX_PATH_LEN];
22419307e5cSMatthew G. Knepley   PetscInt      bs = 0, n;
225b5bcf523SDave May 
226a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
22719307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
22819307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
22919307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields");
23019307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
231cc651181SDave May 
232d52c2f21SMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
23319307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) {
23419307e5cSMatthew G. Knepley     PetscInt fbs;
235d52c2f21SMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
23619307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN));
23719307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL));
23819307e5cSMatthew G. Knepley     bs += fbs;
239d52c2f21SMatthew G. Knepley   }
24019307e5cSMatthew G. Knepley   PetscCall(VecCreate(PetscObjectComm((PetscObject)sw), &x));
2419566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
24219307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE));
24319307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(x, bs));
24419307e5cSMatthew G. Knepley   PetscCall(VecSetDM(x, sw));
2459566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
24657d50842SBarry Smith   PetscCall(VecSetOperation(x, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Swarm));
247b5bcf523SDave May   *vec = x;
2483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
249b5bcf523SDave May }
250b5bcf523SDave May 
251b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
DMCreateLocalVector_Swarm(DM sw,Vec * vec)25219307e5cSMatthew G. Knepley static PetscErrorCode DMCreateLocalVector_Swarm(DM sw, Vec *vec)
253d71ae5a4SJacob Faibussowitsch {
25419307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
25519307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
256b5bcf523SDave May   Vec           x;
257b5bcf523SDave May   char          name[PETSC_MAX_PATH_LEN];
25819307e5cSMatthew G. Knepley   PetscInt      bs = 0, n;
259b5bcf523SDave May 
260a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
26119307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
26219307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
26319307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields");
26419307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
265cc651181SDave May 
266d52c2f21SMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
26719307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) {
26819307e5cSMatthew G. Knepley     PetscInt fbs;
269d52c2f21SMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
27019307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN));
27119307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL));
27219307e5cSMatthew G. Knepley     bs += fbs;
273d52c2f21SMatthew G. Knepley   }
2749566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &x));
2759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
27619307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE));
27719307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(x, bs));
27819307e5cSMatthew G. Knepley   PetscCall(VecSetDM(x, sw));
2799566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
280b5bcf523SDave May   *vec = x;
2813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
282b5bcf523SDave May }
283b5bcf523SDave May 
DMSwarmDestroyVectorFromField_Private(DM dm,const char fieldname[],Vec * vec)284d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
285d71ae5a4SJacob Faibussowitsch {
286fb1bcc12SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
28777048351SPatrick Sanan   DMSwarmDataField gfield;
2882e956fe4SStefano Zampini   PetscInt         bs, nlocal, fid = -1, cfid = -2;
2892e956fe4SStefano Zampini   PetscBool        flg;
290d3a51819SDave May 
291fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
2922e956fe4SStefano Zampini   /* check vector is an inplace array */
2932e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
2942e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg));
295ea17275aSJose E. Roman   (void)flg; /* avoid compiler warning */
296e978a55eSPierre 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);
2979566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(*vec, &nlocal));
2989566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(*vec, &bs));
29908401ef6SPierre 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");
3009566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
3019566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
3028df78e51SMark Adams   PetscCall(VecResetArray(*vec));
3039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(vec));
3043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
305fb1bcc12SMatthew G. Knepley }
306fb1bcc12SMatthew G. Knepley 
DMSwarmCreateVectorFromField_Private(DM dm,const char fieldname[],MPI_Comm comm,Vec * vec)307d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
308d71ae5a4SJacob Faibussowitsch {
309fb1bcc12SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
310fb1bcc12SMatthew G. Knepley   PetscDataType type;
311fb1bcc12SMatthew G. Knepley   PetscScalar  *array;
3122e956fe4SStefano Zampini   PetscInt      bs, n, fid;
313fb1bcc12SMatthew G. Knepley   char          name[PETSC_MAX_PATH_LEN];
314e4fbd051SBarry Smith   PetscMPIInt   size;
3157f92dde0SRylanor   PetscBool     iscuda, iskokkos, iship;
316fb1bcc12SMatthew G. Knepley 
317fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
3189566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
3199566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
3209566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array));
32108401ef6SPierre Jolivet   PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
322fb1bcc12SMatthew G. Knepley 
3239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
3248df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos));
3258df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda));
3267f92dde0SRylanor   PetscCall(PetscStrcmp(dm->vectype, VECHIP, &iship));
3278df78e51SMark Adams   PetscCall(VecCreate(comm, vec));
3288df78e51SMark Adams   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
3298df78e51SMark Adams   PetscCall(VecSetBlockSize(*vec, bs));
3308df78e51SMark Adams   if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS));
3318df78e51SMark Adams   else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA));
3327f92dde0SRylanor   else if (iship) PetscCall(VecSetType(*vec, VECHIP));
3338df78e51SMark Adams   else PetscCall(VecSetType(*vec, VECSTANDARD));
3348df78e51SMark Adams   PetscCall(VecPlaceArray(*vec, array));
3358df78e51SMark Adams 
3369566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname));
3379566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
338fb1bcc12SMatthew G. Knepley 
339fb1bcc12SMatthew G. Knepley   /* Set guard */
3402e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
3412e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid));
34274d0cae8SMatthew G. Knepley 
3439566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*vec, dm));
34457d50842SBarry Smith   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Swarm));
3453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
346fb1bcc12SMatthew G. Knepley }
347fb1bcc12SMatthew G. Knepley 
DMSwarmDestroyVectorFromFields_Private(DM sw,PetscInt Nf,const char * fieldnames[],Vec * vec)34819307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], Vec *vec)
34919307e5cSMatthew G. Knepley {
35019307e5cSMatthew G. Knepley   DM_Swarm          *swarm = (DM_Swarm *)sw->data;
35119307e5cSMatthew G. Knepley   const PetscScalar *array;
35219307e5cSMatthew G. Knepley   PetscInt           bs, n, id = 0, cid = -2;
35319307e5cSMatthew G. Knepley   PetscBool          flg;
35419307e5cSMatthew G. Knepley 
35519307e5cSMatthew G. Knepley   PetscFunctionBegin;
35619307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
35719307e5cSMatthew G. Knepley     PetscInt fid;
35819307e5cSMatthew G. Knepley 
35919307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid));
36019307e5cSMatthew G. Knepley     id += fid;
36119307e5cSMatthew G. Knepley   }
36219307e5cSMatthew G. Knepley   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cid, flg));
36319307e5cSMatthew G. Knepley   (void)flg; /* avoid compiler warning */
36419307e5cSMatthew 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);
36519307e5cSMatthew G. Knepley   PetscCall(VecGetLocalSize(*vec, &n));
36619307e5cSMatthew G. Knepley   PetscCall(VecGetBlockSize(*vec, &bs));
36719307e5cSMatthew G. Knepley   n /= bs;
36819307e5cSMatthew 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");
36919307e5cSMatthew G. Knepley   PetscCall(VecGetArrayRead(*vec, &array));
37019307e5cSMatthew G. Knepley   for (PetscInt f = 0, off = 0; f < Nf; ++f) {
37119307e5cSMatthew G. Knepley     PetscScalar  *farray;
37219307e5cSMatthew G. Knepley     PetscDataType ftype;
37319307e5cSMatthew G. Knepley     PetscInt      fbs;
37419307e5cSMatthew G. Knepley 
37519307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
37619307e5cSMatthew G. Knepley     PetscCheck(off + fbs <= bs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid blocksize %" PetscInt_FMT " < %" PetscInt_FMT, bs, off + fbs);
37719307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i) {
37819307e5cSMatthew G. Knepley       for (PetscInt b = 0; b < fbs; ++b) farray[i * fbs + b] = array[i * bs + off + b];
37919307e5cSMatthew G. Knepley     }
38019307e5cSMatthew G. Knepley     off += fbs;
38119307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
38219307e5cSMatthew G. Knepley   }
38319307e5cSMatthew G. Knepley   PetscCall(VecRestoreArrayRead(*vec, &array));
38419307e5cSMatthew G. Knepley   PetscCall(VecDestroy(vec));
38519307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
38619307e5cSMatthew G. Knepley }
38719307e5cSMatthew G. Knepley 
DMSwarmCreateVectorFromFields_Private(DM sw,PetscInt Nf,const char * fieldnames[],MPI_Comm comm,Vec * vec)38819307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], MPI_Comm comm, Vec *vec)
38919307e5cSMatthew G. Knepley {
39019307e5cSMatthew G. Knepley   DM_Swarm    *swarm = (DM_Swarm *)sw->data;
39119307e5cSMatthew G. Knepley   PetscScalar *array;
39219307e5cSMatthew G. Knepley   PetscInt     n, bs = 0, id = 0;
39319307e5cSMatthew G. Knepley   char         name[PETSC_MAX_PATH_LEN];
39419307e5cSMatthew G. Knepley 
39519307e5cSMatthew G. Knepley   PetscFunctionBegin;
39619307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
39719307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
39819307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
39919307e5cSMatthew G. Knepley     PetscDataType ftype;
40019307e5cSMatthew G. Knepley     PetscInt      fbs;
40119307e5cSMatthew G. Knepley 
40219307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], &fbs, &ftype));
40319307e5cSMatthew G. Knepley     PetscCheck(ftype == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
40419307e5cSMatthew G. Knepley     bs += fbs;
40519307e5cSMatthew G. Knepley   }
40619307e5cSMatthew G. Knepley 
40719307e5cSMatthew G. Knepley   PetscCall(VecCreate(comm, vec));
40819307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
40919307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(*vec, bs));
41019307e5cSMatthew G. Knepley   PetscCall(VecSetType(*vec, sw->vectype));
41119307e5cSMatthew G. Knepley 
41219307e5cSMatthew G. Knepley   PetscCall(VecGetArrayWrite(*vec, &array));
41319307e5cSMatthew G. Knepley   for (PetscInt f = 0, off = 0; f < Nf; ++f) {
41419307e5cSMatthew G. Knepley     PetscScalar  *farray;
41519307e5cSMatthew G. Knepley     PetscDataType ftype;
41619307e5cSMatthew G. Knepley     PetscInt      fbs;
41719307e5cSMatthew G. Knepley 
41819307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
41919307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i) {
42019307e5cSMatthew G. Knepley       for (PetscInt b = 0; b < fbs; ++b) array[i * bs + off + b] = farray[i * fbs + b];
42119307e5cSMatthew G. Knepley     }
42219307e5cSMatthew G. Knepley     off += fbs;
42319307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
42419307e5cSMatthew G. Knepley   }
42519307e5cSMatthew G. Knepley   PetscCall(VecRestoreArrayWrite(*vec, &array));
42619307e5cSMatthew G. Knepley 
42719307e5cSMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
42819307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
42919307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
43019307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, fieldnames[f], PETSC_MAX_PATH_LEN));
43119307e5cSMatthew G. Knepley   }
43219307e5cSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
43319307e5cSMatthew G. Knepley 
43419307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
43519307e5cSMatthew G. Knepley     PetscInt fid;
43619307e5cSMatthew G. Knepley 
43719307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid));
43819307e5cSMatthew G. Knepley     id += fid;
43919307e5cSMatthew G. Knepley   }
44019307e5cSMatthew G. Knepley   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, id));
44119307e5cSMatthew G. Knepley 
44219307e5cSMatthew G. Knepley   PetscCall(VecSetDM(*vec, sw));
44357d50842SBarry Smith   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Swarm));
44419307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
44519307e5cSMatthew G. Knepley }
44619307e5cSMatthew G. Knepley 
4470643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
4480643ed39SMatthew G. Knepley 
4490643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
4500643ed39SMatthew G. Knepley 
4510643ed39SMatthew G. Knepley    and a particle function is given by
4520643ed39SMatthew G. Knepley 
4530643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
4540643ed39SMatthew G. Knepley 
4550643ed39SMatthew G. Knepley    then we want to require that
4560643ed39SMatthew G. Knepley 
4570643ed39SMatthew G. Knepley      M \hat f = M_p f
4580643ed39SMatthew G. Knepley 
4590643ed39SMatthew G. Knepley    where the particle mass matrix is given by
4600643ed39SMatthew G. Knepley 
4610643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
4620643ed39SMatthew G. Knepley 
4630643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
4640643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
4650643ed39SMatthew G. Knepley */
DMSwarmComputeMassMatrix_Private(DM dmc,DM dmf,Mat mass,PetscBool useDeltaFunction,PetscCtx ctx)466*2a8381b2SBarry Smith static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, PetscCtx ctx)
467d71ae5a4SJacob Faibussowitsch {
46883c47955SMatthew G. Knepley   const char   *name = "Mass Matrix";
4690643ed39SMatthew G. Knepley   MPI_Comm      comm;
47019307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
47183c47955SMatthew G. Knepley   PetscDS       prob;
47283c47955SMatthew G. Knepley   PetscSection  fsection, globalFSection;
473e8f14785SLisandro Dalcin   PetscHSetIJ   ht;
4740643ed39SMatthew G. Knepley   PetscLayout   rLayout, colLayout;
47583c47955SMatthew G. Knepley   PetscInt     *dnz, *onz;
476adb2528bSMark Adams   PetscInt      locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4770643ed39SMatthew G. Knepley   PetscReal    *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
47883c47955SMatthew G. Knepley   PetscScalar  *elemMat;
47919307e5cSMatthew G. Knepley   PetscInt      dim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0, totNc = 0;
48019307e5cSMatthew G. Knepley   const char  **coordFields;
48119307e5cSMatthew G. Knepley   PetscReal   **coordVals;
48219307e5cSMatthew G. Knepley   PetscInt     *bs;
48383c47955SMatthew G. Knepley 
48483c47955SMatthew G. Knepley   PetscFunctionBegin;
4859566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
4869566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &dim));
4879566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
4889566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
4899566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
4909566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ));
4919566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
4929566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
4939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
4949566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
49583c47955SMatthew G. Knepley 
49619307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmc, &celldm));
49719307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
49819307e5cSMatthew G. Knepley   PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs));
499d52c2f21SMatthew G. Knepley 
5009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
5019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
5029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
5039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
5049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
5059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
5060643ed39SMatthew G. Knepley 
5079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
5089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
5099566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
5109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
5119566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
5129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
5130643ed39SMatthew G. Knepley 
5149566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
5159566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
51653e60ab4SJoseph Pusztay 
5179566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
51819307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
5190bf7c1c5SMatthew G. Knepley     PetscObject  obj;
5200bf7c1c5SMatthew G. Knepley     PetscClassId id;
5210bf7c1c5SMatthew G. Knepley     PetscInt     Nc;
5220bf7c1c5SMatthew G. Knepley 
5230bf7c1c5SMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5240bf7c1c5SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
5250bf7c1c5SMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
5260bf7c1c5SMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
5270bf7c1c5SMatthew G. Knepley     totNc += Nc;
5280bf7c1c5SMatthew G. Knepley   }
5290643ed39SMatthew G. Knepley   /* count non-zeros */
5309566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
53119307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
5320bf7c1c5SMatthew G. Knepley     PetscObject  obj;
5330bf7c1c5SMatthew G. Knepley     PetscClassId id;
5340bf7c1c5SMatthew G. Knepley     PetscInt     Nc;
5350bf7c1c5SMatthew G. Knepley 
5360bf7c1c5SMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5370bf7c1c5SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
5380bf7c1c5SMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
5390bf7c1c5SMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
5400bf7c1c5SMatthew G. Knepley 
54119307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
5420643ed39SMatthew G. Knepley       PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */
54383c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
54483c47955SMatthew G. Knepley 
5459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5469566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
547fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
54883c47955SMatthew G. Knepley       {
549e8f14785SLisandro Dalcin         PetscHashIJKey key;
550e8f14785SLisandro Dalcin         PetscBool      missing;
5510bf7c1c5SMatthew G. Knepley         for (PetscInt i = 0; i < numFIndices; ++i) {
552adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
553adb2528bSMark Adams           if (key.j >= 0) {
55483c47955SMatthew G. Knepley             /* Get indices for coarse elements */
5550bf7c1c5SMatthew G. Knepley             for (PetscInt j = 0; j < numCIndices; ++j) {
5560bf7c1c5SMatthew G. Knepley               for (PetscInt c = 0; c < Nc; ++c) {
5570bf7c1c5SMatthew G. Knepley                 // TODO Need field offset on particle here
5580bf7c1c5SMatthew G. Knepley                 key.i = cindices[j] * totNc + c + rStart; /* global cols (from Swarm) */
559adb2528bSMark Adams                 if (key.i < 0) continue;
5609566063dSJacob Faibussowitsch                 PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
561966bd95aSPierre Jolivet                 PetscCheck(missing, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j);
5620643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
563e8f14785SLisandro Dalcin                 else ++onz[key.i - rStart];
56483c47955SMatthew G. Knepley               }
565fc7c92abSMatthew G. Knepley             }
566fc7c92abSMatthew G. Knepley           }
5670bf7c1c5SMatthew G. Knepley         }
568fe11354eSMatthew G. Knepley         PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
56983c47955SMatthew G. Knepley       }
5709566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
57183c47955SMatthew G. Knepley     }
57283c47955SMatthew G. Knepley   }
5739566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
5749566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
5759566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
5769566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
5770bf7c1c5SMatthew G. Knepley   PetscCall(PetscMalloc3(maxC * totNc * totDim, &elemMat, maxC * totNc, &rowIDXs, maxC * dim, &xi));
57819307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
579ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
58083c47955SMatthew G. Knepley     PetscObject     obj;
581ad9634fcSMatthew G. Knepley     PetscClassId    id;
58219307e5cSMatthew G. Knepley     PetscInt        Nc;
58383c47955SMatthew G. Knepley 
5849566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
585ad9634fcSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
586ad9634fcSMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
587ad9634fcSMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
588ea7032a0SMatthew G. Knepley 
58919307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
59019307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
59183c47955SMatthew G. Knepley       PetscInt *findices, *cindices;
59283c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
59383c47955SMatthew G. Knepley 
5940643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5959566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
5969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5979566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
59819307e5cSMatthew G. Knepley       for (PetscInt j = 0; j < numCIndices; ++j) {
59919307e5cSMatthew G. Knepley         PetscReal xr[8];
60019307e5cSMatthew G. Knepley         PetscInt  off = 0;
60119307e5cSMatthew G. Knepley 
60219307e5cSMatthew G. Knepley         for (PetscInt i = 0; i < Nfc; ++i) {
60319307e5cSMatthew G. Knepley           for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[j] * bs[i] + b];
60419307e5cSMatthew G. Knepley         }
60519307e5cSMatthew 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);
60619307e5cSMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, xr, &xi[j * dim]);
60719307e5cSMatthew G. Knepley       }
608ad9634fcSMatthew G. Knepley       if (id == PETSCFE_CLASSID) PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
609ad9634fcSMatthew G. Knepley       else PetscCall(PetscFVCreateTabulation((PetscFV)obj, 1, numCIndices, xi, 0, &Tcoarse));
61083c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
6110bf7c1c5SMatthew G. Knepley       PetscCall(PetscArrayzero(elemMat, numCIndices * Nc * totDim));
6120bf7c1c5SMatthew G. Knepley       for (PetscInt i = 0; i < numFIndices / Nc; ++i) {
6130bf7c1c5SMatthew G. Knepley         for (PetscInt j = 0; j < numCIndices; ++j) {
6140bf7c1c5SMatthew G. Knepley           for (PetscInt c = 0; c < Nc; ++c) {
6150bf7c1c5SMatthew G. Knepley             // TODO Need field offset on particle and field here
6160643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
6170bf7c1c5SMatthew G. Knepley             elemMat[(j * totNc + c) * numFIndices + i * Nc + c] += Tcoarse->T[0][(j * numFIndices + i * Nc + c) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
61883c47955SMatthew G. Knepley           }
6190643ed39SMatthew G. Knepley         }
6200643ed39SMatthew G. Knepley       }
6210bf7c1c5SMatthew G. Knepley       for (PetscInt j = 0; j < numCIndices; ++j)
6220bf7c1c5SMatthew G. Knepley         // TODO Need field offset on particle here
6230bf7c1c5SMatthew G. Knepley         for (PetscInt c = 0; c < Nc; ++c) rowIDXs[j * Nc + c] = cindices[j] * totNc + c + rStart;
6240bf7c1c5SMatthew G. Knepley       if (0) PetscCall(DMPrintCellMatrix(cell, name, numCIndices * Nc, numFIndices, elemMat));
6250bf7c1c5SMatthew G. Knepley       PetscCall(MatSetValues(mass, numCIndices * Nc, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES));
626fe11354eSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
6279566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
6289566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
62983c47955SMatthew G. Knepley     }
63019307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
63183c47955SMatthew G. Knepley   }
6329566063dSJacob Faibussowitsch   PetscCall(PetscFree3(elemMat, rowIDXs, xi));
6339566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
6349566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
63519307e5cSMatthew G. Knepley   PetscCall(PetscFree2(coordVals, bs));
6369566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
6379566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
6383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63983c47955SMatthew G. Knepley }
64083c47955SMatthew G. Knepley 
641d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */
DMCreateMatrix_Swarm(DM sw,Mat * m)642d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m)
643d71ae5a4SJacob Faibussowitsch {
644d0c080abSJoseph Pusztay   Vec      field;
645d0c080abSJoseph Pusztay   PetscInt size;
646d0c080abSJoseph Pusztay 
647d0c080abSJoseph Pusztay   PetscFunctionBegin;
6489566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(sw, &field));
6499566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(field, &size));
6509566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(sw, &field));
6519566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, m));
6529566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*m));
6539566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size));
6549566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL));
6559566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(*m));
6569566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY));
6579566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY));
6589566063dSJacob Faibussowitsch   PetscCall(MatShift(*m, 1.0));
6599566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*m, sw));
6603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
661d0c080abSJoseph Pusztay }
662d0c080abSJoseph Pusztay 
663adb2528bSMark Adams /* FEM cols, Particle rows */
DMCreateMassMatrix_Swarm(DM dmCoarse,DM dmFine,Mat * mass)664d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
665d71ae5a4SJacob Faibussowitsch {
66619307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
667895a1698SMatthew G. Knepley   PetscSection  gsf;
66819307e5cSMatthew G. Knepley   PetscInt      m, n, Np, bs;
66983c47955SMatthew G. Knepley   void         *ctx;
67083c47955SMatthew G. Knepley 
67183c47955SMatthew G. Knepley   PetscFunctionBegin;
67219307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmCoarse, &celldm));
67319307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)dmCoarse), PETSC_ERR_USER, "Active cell DM does not define any fields");
6749566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
6759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
6760bf7c1c5SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dmCoarse, &Np));
67719307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetBlockSize(celldm, dmCoarse, &bs));
67819307e5cSMatthew G. Knepley   n = Np * bs;
6799566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
6809566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE));
6819566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
6829566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
68383c47955SMatthew G. Knepley 
6849566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
6859566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
6863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68783c47955SMatthew G. Knepley }
68883c47955SMatthew G. Knepley 
DMSwarmComputeMassMatrixSquare_Private(DM dmc,DM dmf,Mat mass,PetscBool useDeltaFunction,PetscCtx ctx)689*2a8381b2SBarry Smith static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, PetscCtx ctx)
690d71ae5a4SJacob Faibussowitsch {
6914cc7f7b2SMatthew G. Knepley   const char   *name = "Mass Matrix Square";
6924cc7f7b2SMatthew G. Knepley   MPI_Comm      comm;
69319307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
6944cc7f7b2SMatthew G. Knepley   PetscDS       prob;
6954cc7f7b2SMatthew G. Knepley   PetscSection  fsection, globalFSection;
6964cc7f7b2SMatthew G. Knepley   PetscHSetIJ   ht;
6974cc7f7b2SMatthew G. Knepley   PetscLayout   rLayout, colLayout;
6984cc7f7b2SMatthew G. Knepley   PetscInt     *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
6994cc7f7b2SMatthew G. Knepley   PetscInt      locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
7004cc7f7b2SMatthew G. Knepley   PetscReal    *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
7014cc7f7b2SMatthew G. Knepley   PetscScalar  *elemMat, *elemMatSq;
70219307e5cSMatthew G. Knepley   PetscInt      cdim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0;
70319307e5cSMatthew G. Knepley   const char  **coordFields;
70419307e5cSMatthew G. Knepley   PetscReal   **coordVals;
70519307e5cSMatthew G. Knepley   PetscInt     *bs;
7064cc7f7b2SMatthew G. Knepley 
7074cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
7089566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
7099566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &cdim));
7109566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
7119566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
7129566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
7139566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ));
7149566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
7159566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
7179566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
7184cc7f7b2SMatthew G. Knepley 
71919307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmc, &celldm));
72019307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
72119307e5cSMatthew G. Knepley   PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs));
722d52c2f21SMatthew G. Knepley 
7239566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
7249566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
7259566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
7269566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
7279566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
7289566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
7294cc7f7b2SMatthew G. Knepley 
7309566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
7319566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
7329566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
7339566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
7349566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
7359566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
7364cc7f7b2SMatthew G. Knepley 
7379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmf, &depth));
7389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize));
7394cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth);
7409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxAdjSize, &adj));
7414cc7f7b2SMatthew G. Knepley 
7429566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
7439566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
7444cc7f7b2SMatthew G. Knepley   /* Count nonzeros
7454cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
7464cc7f7b2SMatthew G. Knepley   */
7479566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
74819307e5cSMatthew G. Knepley   for (PetscInt cell = cStart; cell < cEnd; ++cell) {
7494cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
7504cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
7514cc7f7b2SMatthew G. Knepley #if 0
7524cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
7534cc7f7b2SMatthew G. Knepley #endif
7544cc7f7b2SMatthew G. Knepley 
7559566063dSJacob Faibussowitsch     PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
7564cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
7574cc7f7b2SMatthew G. Knepley     /* Diagonal block */
75819307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices;
7594cc7f7b2SMatthew G. Knepley #if 0
7604cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
7619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj));
7624cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
7634cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
7644cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
7654cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
7664cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
7674cc7f7b2SMatthew G. Knepley 
7689566063dSJacob Faibussowitsch         PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
7694cc7f7b2SMatthew G. Knepley         {
7704cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
7714cc7f7b2SMatthew G. Knepley           PetscBool      missing;
7724cc7f7b2SMatthew G. Knepley 
7734cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
7744cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
7754cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
7764cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
7774cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
7784cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
7799566063dSJacob Faibussowitsch               PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
7804cc7f7b2SMatthew G. Knepley               if (missing) {
7814cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
7824cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
7834cc7f7b2SMatthew G. Knepley               }
7844cc7f7b2SMatthew G. Knepley             }
7854cc7f7b2SMatthew G. Knepley           }
7864cc7f7b2SMatthew G. Knepley         }
787fe11354eSMatthew G. Knepley         PetscCall(DMSwarmSortRestorePointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
7884cc7f7b2SMatthew G. Knepley       }
7894cc7f7b2SMatthew G. Knepley     }
7904cc7f7b2SMatthew G. Knepley #endif
791fe11354eSMatthew G. Knepley     PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
7924cc7f7b2SMatthew G. Knepley   }
7939566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
7949566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
7959566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
7969566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
7979566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi));
7984cc7f7b2SMatthew G. Knepley   /* Fill in values
7994cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
8004cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
8014cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
8024cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
8034cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
8044cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
8054cc7f7b2SMatthew G. Knepley          Insert block
8064cc7f7b2SMatthew G. Knepley   */
80719307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
8084cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
8094cc7f7b2SMatthew G. Knepley     PetscObject     obj;
81019307e5cSMatthew G. Knepley     PetscInt        Nc;
8114cc7f7b2SMatthew G. Knepley 
8129566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
8139566063dSJacob Faibussowitsch     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
81463a3b9bcSJacob Faibussowitsch     PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc);
81519307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
81619307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
8174cc7f7b2SMatthew G. Knepley       PetscInt *findices, *cindices;
8184cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
8194cc7f7b2SMatthew G. Knepley 
8204cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
8219566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
8229566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
8239566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
82419307e5cSMatthew G. Knepley       for (PetscInt p = 0; p < numCIndices; ++p) {
82519307e5cSMatthew G. Knepley         PetscReal xr[8];
82619307e5cSMatthew G. Knepley         PetscInt  off = 0;
82719307e5cSMatthew G. Knepley 
82819307e5cSMatthew G. Knepley         for (PetscInt i = 0; i < Nfc; ++i) {
82919307e5cSMatthew G. Knepley           for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[p] * bs[i] + b];
83019307e5cSMatthew G. Knepley         }
83119307e5cSMatthew 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);
83219307e5cSMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, xr, &xi[p * cdim]);
83319307e5cSMatthew G. Knepley       }
8349566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
8354cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
8369566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elemMat, numCIndices * totDim));
83719307e5cSMatthew G. Knepley       for (PetscInt i = 0; i < numFIndices; ++i) {
83819307e5cSMatthew G. Knepley         for (PetscInt p = 0; p < numCIndices; ++p) {
83919307e5cSMatthew G. Knepley           for (PetscInt c = 0; c < Nc; ++c) {
8404cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
8414cc7f7b2SMatthew G. Knepley             elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
8424cc7f7b2SMatthew G. Knepley           }
8434cc7f7b2SMatthew G. Knepley         }
8444cc7f7b2SMatthew G. Knepley       }
8459566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
84619307e5cSMatthew G. Knepley       for (PetscInt p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
8479566063dSJacob Faibussowitsch       if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
8484cc7f7b2SMatthew G. Knepley       /* Block diagonal */
84978884ca7SMatthew G. Knepley       if (numCIndices) {
8504cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
8514cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
8524cc7f7b2SMatthew G. Knepley 
8539566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numCIndices, &blasn));
8549566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numFIndices, &blask));
855792fecdfSBarry Smith         PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn));
8564cc7f7b2SMatthew G. Knepley       }
8579566063dSJacob Faibussowitsch       PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES));
8584cf0e950SBarry Smith       /* TODO off-diagonal */
859fe11354eSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
8609566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
8614cc7f7b2SMatthew G. Knepley     }
86219307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
8634cc7f7b2SMatthew G. Knepley   }
8649566063dSJacob Faibussowitsch   PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi));
8659566063dSJacob Faibussowitsch   PetscCall(PetscFree(adj));
8669566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
8679566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
86819307e5cSMatthew G. Knepley   PetscCall(PetscFree2(coordVals, bs));
8699566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
8709566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
8713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8724cc7f7b2SMatthew G. Knepley }
8734cc7f7b2SMatthew G. Knepley 
874cc4c1da9SBarry Smith /*@
8754cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
8764cc7f7b2SMatthew G. Knepley 
87720f4b53cSBarry Smith   Collective
8784cc7f7b2SMatthew G. Knepley 
87960225df5SJacob Faibussowitsch   Input Parameters:
88020f4b53cSBarry Smith + dmCoarse - a `DMSWARM`
88120f4b53cSBarry Smith - dmFine   - a `DMPLEX`
8824cc7f7b2SMatthew G. Knepley 
88360225df5SJacob Faibussowitsch   Output Parameter:
8844cc7f7b2SMatthew G. Knepley . mass - the square of the particle mass matrix
8854cc7f7b2SMatthew G. Knepley 
8864cc7f7b2SMatthew G. Knepley   Level: advanced
8874cc7f7b2SMatthew G. Knepley 
88820f4b53cSBarry Smith   Note:
8894cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
8904cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
8914cc7f7b2SMatthew G. Knepley 
89220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMCreateMassMatrix()`
8934cc7f7b2SMatthew G. Knepley @*/
DMSwarmCreateMassMatrixSquare(DM dmCoarse,DM dmFine,Mat * mass)894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
895d71ae5a4SJacob Faibussowitsch {
8964cc7f7b2SMatthew G. Knepley   PetscInt n;
8974cc7f7b2SMatthew G. Knepley   void    *ctx;
8984cc7f7b2SMatthew G. Knepley 
8994cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
9009566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dmCoarse, &n));
9019566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
9029566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE));
9039566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
9049566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
9054cc7f7b2SMatthew G. Knepley 
9069566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
9079566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view"));
9083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9094cc7f7b2SMatthew G. Knepley }
9104cc7f7b2SMatthew G. Knepley 
9111898fd5cSMatthew G. Knepley /* This creates a "gradient matrix" between a finite element and particle space, which is meant to enforce a weak divergence condition on the particle space. We are looking for a finite element field that has the same divergence as our particle field, so that
9121898fd5cSMatthew G. Knepley 
9131898fd5cSMatthew G. Knepley      \int_X \psi_i \nabla \cdot \hat f = \int_X \psi_i \nabla \cdot f
9141898fd5cSMatthew G. Knepley 
9151898fd5cSMatthew G. Knepley    and then integrate by parts
9161898fd5cSMatthew G. Knepley 
9171898fd5cSMatthew G. Knepley      \int_X \nabla \psi_i \cdot \hat f = \int_X \nabla \psi_i \cdot f
9181898fd5cSMatthew G. Knepley 
9191898fd5cSMatthew G. Knepley    where \psi is from a scalar FE space. If a finite element interpolant is given by
9201898fd5cSMatthew G. Knepley 
9211898fd5cSMatthew G. Knepley      \hat f^c = \sum_i f_i \phi^c_i
9221898fd5cSMatthew G. Knepley 
9231898fd5cSMatthew G. Knepley    and a particle function is given by
9241898fd5cSMatthew G. Knepley 
9251898fd5cSMatthew G. Knepley      f^c = \sum_p f^c_p \delta(x - x_p)
9261898fd5cSMatthew G. Knepley 
9271898fd5cSMatthew G. Knepley    then we want to require that
9281898fd5cSMatthew G. Knepley 
9291898fd5cSMatthew G. Knepley      D_f \hat f = D_p f
9301898fd5cSMatthew G. Knepley 
9311898fd5cSMatthew G. Knepley    where the gradient matrices are given by
9321898fd5cSMatthew G. Knepley 
9331898fd5cSMatthew G. Knepley      (D_f)_{i(jc)} = \int \partial_c \psi_i \phi_j
9341898fd5cSMatthew G. Knepley      (D_p)_{i(jc)} = \int \partial_c \psi_i \delta(x - x_j)
9351898fd5cSMatthew G. Knepley 
9361898fd5cSMatthew G. Knepley    Thus we need two finite element spaces, a scalar and a vector. The vector space holds the representer for the
9371898fd5cSMatthew G. Knepley    vector particle field. The scalar space holds the output of D_p or D_f, which is the weak divergence of the field.
9381898fd5cSMatthew G. Knepley 
9391898fd5cSMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
9401898fd5cSMatthew G. Knepley    his integral. We allow this with the boolean flag.
9411898fd5cSMatthew G. Knepley */
DMSwarmComputeGradientMatrix_Private(DM sw,DM dm,Mat derv,PetscBool useDeltaFunction,PetscCtx ctx)942*2a8381b2SBarry Smith static PetscErrorCode DMSwarmComputeGradientMatrix_Private(DM sw, DM dm, Mat derv, PetscBool useDeltaFunction, PetscCtx ctx)
9431898fd5cSMatthew G. Knepley {
9441898fd5cSMatthew G. Knepley   const char   *name = "Derivative Matrix";
9451898fd5cSMatthew G. Knepley   MPI_Comm      comm;
9461898fd5cSMatthew G. Knepley   DMSwarmCellDM celldm;
9471898fd5cSMatthew G. Knepley   PetscDS       ds;
9481898fd5cSMatthew G. Knepley   PetscSection  fsection, globalFSection;
9491898fd5cSMatthew G. Knepley   PetscLayout   rLayout;
9501898fd5cSMatthew G. Knepley   PetscInt      locRows, rStart, *rowIDXs;
9511898fd5cSMatthew G. Knepley   PetscReal    *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
9521898fd5cSMatthew G. Knepley   PetscScalar  *elemMat;
9531898fd5cSMatthew G. Knepley   PetscInt      cdim, Nf, Nfc, cStart, cEnd, totDim, maxNpc = 0, totNc = 0;
9541898fd5cSMatthew G. Knepley   const char  **coordFields;
9551898fd5cSMatthew G. Knepley   PetscReal   **coordVals;
9561898fd5cSMatthew G. Knepley   PetscInt     *bs;
9571898fd5cSMatthew G. Knepley 
9581898fd5cSMatthew G. Knepley   PetscFunctionBegin;
9591898fd5cSMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)derv, &comm));
9601898fd5cSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &cdim));
9611898fd5cSMatthew G. Knepley   PetscCall(DMGetDS(dm, &ds));
9621898fd5cSMatthew G. Knepley   PetscCall(PetscDSGetNumFields(ds, &Nf));
9631898fd5cSMatthew G. Knepley   PetscCheck(Nf == 1, comm, PETSC_ERR_SUP, "Currently, we only support a single field");
9641898fd5cSMatthew G. Knepley   PetscCall(PetscDSGetTotalDimension(ds, &totDim));
9651898fd5cSMatthew G. Knepley   PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ));
9661898fd5cSMatthew G. Knepley   PetscCall(DMGetLocalSection(dm, &fsection));
9671898fd5cSMatthew G. Knepley   PetscCall(DMGetGlobalSection(dm, &globalFSection));
9681898fd5cSMatthew G. Knepley   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
9691898fd5cSMatthew G. Knepley   PetscCall(MatGetLocalSize(derv, &locRows, NULL));
9701898fd5cSMatthew G. Knepley 
9711898fd5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
9721898fd5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
9731898fd5cSMatthew G. Knepley   PetscCheck(Nfc == 1, comm, PETSC_ERR_SUP, "Currently, we only support a single field");
9741898fd5cSMatthew G. Knepley   PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs));
9751898fd5cSMatthew G. Knepley 
9761898fd5cSMatthew G. Knepley   PetscCall(PetscLayoutCreate(comm, &rLayout));
9771898fd5cSMatthew G. Knepley   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
9781898fd5cSMatthew G. Knepley   PetscCall(PetscLayoutSetBlockSize(rLayout, cdim));
9791898fd5cSMatthew G. Knepley   PetscCall(PetscLayoutSetUp(rLayout));
9801898fd5cSMatthew G. Knepley   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
9811898fd5cSMatthew G. Knepley   PetscCall(PetscLayoutDestroy(&rLayout));
9821898fd5cSMatthew G. Knepley 
9831898fd5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
9841898fd5cSMatthew G. Knepley     PetscObject obj;
9851898fd5cSMatthew G. Knepley     PetscInt    Nc;
9861898fd5cSMatthew G. Knepley 
9871898fd5cSMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(ds, field, &obj));
9881898fd5cSMatthew G. Knepley     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
9891898fd5cSMatthew G. Knepley     totNc += Nc;
9901898fd5cSMatthew G. Knepley   }
9911898fd5cSMatthew G. Knepley   PetscCheck(totNc == 1, comm, PETSC_ERR_ARG_WRONG, "The number of field components %" PetscInt_FMT " != 1", totNc);
9921898fd5cSMatthew G. Knepley   /* count non-zeros */
9931898fd5cSMatthew G. Knepley   PetscCall(DMSwarmSortGetAccess(sw));
9941898fd5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
9951898fd5cSMatthew G. Knepley     PetscObject obj;
9961898fd5cSMatthew G. Knepley     PetscInt    Nc;
9971898fd5cSMatthew G. Knepley 
9981898fd5cSMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(ds, field, &obj));
9991898fd5cSMatthew G. Knepley     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
10001898fd5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
10011898fd5cSMatthew G. Knepley       PetscInt *pind;
10021898fd5cSMatthew G. Knepley       PetscInt  Npc;
10031898fd5cSMatthew G. Knepley 
10041898fd5cSMatthew G. Knepley       PetscCall(DMSwarmSortGetPointsPerCell(sw, cell, &Npc, &pind));
10051898fd5cSMatthew G. Knepley       maxNpc = PetscMax(maxNpc, Npc);
10061898fd5cSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(sw, cell, &Npc, &pind));
10071898fd5cSMatthew G. Knepley     }
10081898fd5cSMatthew G. Knepley   }
10091898fd5cSMatthew G. Knepley   PetscCall(PetscMalloc3(maxNpc * cdim * totDim, &elemMat, maxNpc * cdim, &rowIDXs, maxNpc * cdim, &xi));
10101898fd5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
10111898fd5cSMatthew G. Knepley     PetscTabulation Tcoarse;
10121898fd5cSMatthew G. Knepley     PetscFE         fe;
10131898fd5cSMatthew G. Knepley 
10141898fd5cSMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(ds, field, (PetscObject *)&fe));
10151898fd5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(sw, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
10161898fd5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
10171898fd5cSMatthew G. Knepley       PetscInt *findices, *pind;
10181898fd5cSMatthew G. Knepley       PetscInt  numFIndices, Npc;
10191898fd5cSMatthew G. Knepley 
10201898fd5cSMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
10211898fd5cSMatthew G. Knepley       PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, invJ, &detJ));
10221898fd5cSMatthew G. Knepley       PetscCall(DMPlexGetClosureIndices(dm, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
10231898fd5cSMatthew G. Knepley       PetscCall(DMSwarmSortGetPointsPerCell(sw, cell, &Npc, &pind));
10241898fd5cSMatthew G. Knepley       for (PetscInt j = 0; j < Npc; ++j) {
10251898fd5cSMatthew G. Knepley         PetscReal xr[8];
10261898fd5cSMatthew G. Knepley         PetscInt  off = 0;
10271898fd5cSMatthew G. Knepley 
10281898fd5cSMatthew G. Knepley         for (PetscInt i = 0; i < Nfc; ++i) {
10291898fd5cSMatthew G. Knepley           for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][pind[j] * bs[i] + b];
10301898fd5cSMatthew G. Knepley         }
10311898fd5cSMatthew 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);
10321898fd5cSMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, xr, &xi[j * cdim]);
10331898fd5cSMatthew G. Knepley       }
10341898fd5cSMatthew G. Knepley       PetscCall(PetscFECreateTabulation(fe, 1, Npc, xi, 1, &Tcoarse));
10351898fd5cSMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
10361898fd5cSMatthew G. Knepley       PetscCall(PetscArrayzero(elemMat, Npc * cdim * totDim));
10371898fd5cSMatthew G. Knepley       for (PetscInt i = 0; i < numFIndices; ++i) {
10381898fd5cSMatthew G. Knepley         for (PetscInt j = 0; j < Npc; ++j) {
10398c5add6aSPierre Jolivet           /* D[((p*pdim + i)*Nc + c)*cdim + d] is the value at point p for basis function i, component c, derivative d */
10401898fd5cSMatthew G. Knepley           for (PetscInt d = 0; d < cdim; ++d) {
10411898fd5cSMatthew G. Knepley             xi[d] = 0.;
10421898fd5cSMatthew G. Knepley             for (PetscInt e = 0; e < cdim; ++e) xi[d] += invJ[e * cdim + d] * Tcoarse->T[1][(j * numFIndices + i) * cdim + e];
10431898fd5cSMatthew G. Knepley             elemMat[(j * cdim + d) * numFIndices + i] += xi[d] * (useDeltaFunction ? 1.0 : detJ);
10441898fd5cSMatthew G. Knepley           }
10451898fd5cSMatthew G. Knepley         }
10461898fd5cSMatthew G. Knepley       }
10471898fd5cSMatthew G. Knepley       for (PetscInt j = 0; j < Npc; ++j)
10481898fd5cSMatthew G. Knepley         for (PetscInt d = 0; d < cdim; ++d) rowIDXs[j * cdim + d] = pind[j] * cdim + d + rStart;
10491898fd5cSMatthew G. Knepley       if (0) PetscCall(DMPrintCellMatrix(cell, name, Npc * cdim, numFIndices, elemMat));
10501898fd5cSMatthew G. Knepley       PetscCall(MatSetValues(derv, Npc * cdim, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES));
10511898fd5cSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(sw, cell, &Npc, &pind));
10521898fd5cSMatthew G. Knepley       PetscCall(DMPlexRestoreClosureIndices(dm, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
10531898fd5cSMatthew G. Knepley       PetscCall(PetscTabulationDestroy(&Tcoarse));
10541898fd5cSMatthew G. Knepley     }
10551898fd5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(sw, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
10561898fd5cSMatthew G. Knepley   }
10571898fd5cSMatthew G. Knepley   PetscCall(PetscFree3(elemMat, rowIDXs, xi));
10581898fd5cSMatthew G. Knepley   PetscCall(DMSwarmSortRestoreAccess(sw));
10591898fd5cSMatthew G. Knepley   PetscCall(PetscFree3(v0, J, invJ));
10601898fd5cSMatthew G. Knepley   PetscCall(PetscFree2(coordVals, bs));
10611898fd5cSMatthew G. Knepley   PetscCall(MatAssemblyBegin(derv, MAT_FINAL_ASSEMBLY));
10621898fd5cSMatthew G. Knepley   PetscCall(MatAssemblyEnd(derv, MAT_FINAL_ASSEMBLY));
10631898fd5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
10641898fd5cSMatthew G. Knepley }
10651898fd5cSMatthew G. Knepley 
10661898fd5cSMatthew G. Knepley /* FEM cols:      this is a scalar space
10671898fd5cSMatthew G. Knepley    Particle rows: this is a vector space that contracts with the derivative
10681898fd5cSMatthew G. Knepley */
DMCreateGradientMatrix_Swarm(DM sw,DM dm,Mat * derv)10691898fd5cSMatthew G. Knepley static PetscErrorCode DMCreateGradientMatrix_Swarm(DM sw, DM dm, Mat *derv)
10701898fd5cSMatthew G. Knepley {
10711898fd5cSMatthew G. Knepley   DMSwarmCellDM celldm;
10721898fd5cSMatthew G. Knepley   PetscSection  gs;
10731898fd5cSMatthew G. Knepley   PetscInt      cdim, m, n, Np, bs;
10741898fd5cSMatthew G. Knepley   void         *ctx;
10751898fd5cSMatthew G. Knepley   MPI_Comm      comm;
10761898fd5cSMatthew G. Knepley 
10771898fd5cSMatthew G. Knepley   PetscFunctionBegin;
10781898fd5cSMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
10791898fd5cSMatthew G. Knepley   PetscCall(DMGetCoordinateDim(dm, &cdim));
10801898fd5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
10811898fd5cSMatthew G. Knepley   PetscCheck(celldm->Nf, comm, PETSC_ERR_USER, "Active cell DM does not define any fields");
10821898fd5cSMatthew G. Knepley   PetscCall(DMGetGlobalSection(dm, &gs));
10831898fd5cSMatthew G. Knepley   PetscCall(PetscSectionGetConstrainedStorageSize(gs, &n));
10841898fd5cSMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(sw, &Np));
10851898fd5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetBlockSize(celldm, sw, &bs));
10861898fd5cSMatthew G. Knepley   PetscCheck(cdim == bs, comm, PETSC_ERR_ARG_WRONG, "Coordinate dimension %" PetscInt_FMT " != %" PetscInt_FMT " swarm field block size", cdim, bs);
10871898fd5cSMatthew G. Knepley   m = Np * bs;
10881898fd5cSMatthew G. Knepley   PetscCall(MatCreate(PetscObjectComm((PetscObject)sw), derv));
10891898fd5cSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*derv, "Swarm Derivative Matrix"));
10901898fd5cSMatthew G. Knepley   PetscCall(MatSetSizes(*derv, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
10911898fd5cSMatthew G. Knepley   PetscCall(MatSetType(*derv, sw->mattype));
10921898fd5cSMatthew G. Knepley   PetscCall(DMGetApplicationContext(dm, &ctx));
10931898fd5cSMatthew G. Knepley 
10941898fd5cSMatthew G. Knepley   PetscCall(DMSwarmComputeGradientMatrix_Private(sw, dm, *derv, PETSC_TRUE, ctx));
10951898fd5cSMatthew G. Knepley   PetscCall(MatViewFromOptions(*derv, NULL, "-gradient_mat_view"));
10961898fd5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
10971898fd5cSMatthew G. Knepley }
10981898fd5cSMatthew G. Knepley 
1099cc4c1da9SBarry Smith /*@
110020f4b53cSBarry Smith   DMSwarmCreateGlobalVectorFromField - Creates a `Vec` object sharing the array associated with a given field
1101d3a51819SDave May 
110220f4b53cSBarry Smith   Collective
1103d3a51819SDave May 
110460225df5SJacob Faibussowitsch   Input Parameters:
110520f4b53cSBarry Smith + dm        - a `DMSWARM`
110662741f57SDave May - fieldname - the textual name given to a registered field
1107d3a51819SDave May 
110860225df5SJacob Faibussowitsch   Output Parameter:
1109d3a51819SDave May . vec - the vector
1110d3a51819SDave May 
1111d3a51819SDave May   Level: beginner
1112d3a51819SDave May 
1113cc4c1da9SBarry Smith   Note:
111420f4b53cSBarry Smith   The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromField()`.
11158b8a3813SDave May 
111620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()`
1117d3a51819SDave May @*/
DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec * vec)1118d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
1119d71ae5a4SJacob Faibussowitsch {
1120fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
1121b5bcf523SDave May 
1122fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
1123ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
11249566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
11253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1126b5bcf523SDave May }
1127b5bcf523SDave May 
1128cc4c1da9SBarry Smith /*@
112920f4b53cSBarry Smith   DMSwarmDestroyGlobalVectorFromField - Destroys the `Vec` object which share the array associated with a given field
1130d3a51819SDave May 
113120f4b53cSBarry Smith   Collective
1132d3a51819SDave May 
113360225df5SJacob Faibussowitsch   Input Parameters:
113420f4b53cSBarry Smith + dm        - a `DMSWARM`
113562741f57SDave May - fieldname - the textual name given to a registered field
1136d3a51819SDave May 
113760225df5SJacob Faibussowitsch   Output Parameter:
1138d3a51819SDave May . vec - the vector
1139d3a51819SDave May 
1140d3a51819SDave May   Level: beginner
1141d3a51819SDave May 
114220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
1143d3a51819SDave May @*/
DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec * vec)1144d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
1145d71ae5a4SJacob Faibussowitsch {
1146fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
1147ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
11489566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
11493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1150b5bcf523SDave May }
1151b5bcf523SDave May 
1152cc4c1da9SBarry Smith /*@
115320f4b53cSBarry Smith   DMSwarmCreateLocalVectorFromField - Creates a `Vec` object sharing the array associated with a given field
1154fb1bcc12SMatthew G. Knepley 
115520f4b53cSBarry Smith   Collective
1156fb1bcc12SMatthew G. Knepley 
115760225df5SJacob Faibussowitsch   Input Parameters:
115820f4b53cSBarry Smith + dm        - a `DMSWARM`
115962741f57SDave May - fieldname - the textual name given to a registered field
1160fb1bcc12SMatthew G. Knepley 
116160225df5SJacob Faibussowitsch   Output Parameter:
1162fb1bcc12SMatthew G. Knepley . vec - the vector
1163fb1bcc12SMatthew G. Knepley 
1164fb1bcc12SMatthew G. Knepley   Level: beginner
1165fb1bcc12SMatthew G. Knepley 
116620f4b53cSBarry Smith   Note:
11678b8a3813SDave May   The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
11688b8a3813SDave May 
116920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
1170fb1bcc12SMatthew G. Knepley @*/
DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec * vec)1171d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
1172d71ae5a4SJacob Faibussowitsch {
1173fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
1174bbe8250bSMatthew G. Knepley 
1175fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
11769566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
11773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1178bbe8250bSMatthew G. Knepley }
1179fb1bcc12SMatthew G. Knepley 
1180cc4c1da9SBarry Smith /*@
118120f4b53cSBarry Smith   DMSwarmDestroyLocalVectorFromField - Destroys the `Vec` object which share the array associated with a given field
1182fb1bcc12SMatthew G. Knepley 
118320f4b53cSBarry Smith   Collective
1184fb1bcc12SMatthew G. Knepley 
118560225df5SJacob Faibussowitsch   Input Parameters:
118620f4b53cSBarry Smith + dm        - a `DMSWARM`
118762741f57SDave May - fieldname - the textual name given to a registered field
1188fb1bcc12SMatthew G. Knepley 
118960225df5SJacob Faibussowitsch   Output Parameter:
1190fb1bcc12SMatthew G. Knepley . vec - the vector
1191fb1bcc12SMatthew G. Knepley 
1192fb1bcc12SMatthew G. Knepley   Level: beginner
1193fb1bcc12SMatthew G. Knepley 
119420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()`
1195fb1bcc12SMatthew G. Knepley @*/
DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec * vec)1196d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
1197d71ae5a4SJacob Faibussowitsch {
1198fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
1199ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
12009566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
12013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1202bbe8250bSMatthew G. Knepley }
1203bbe8250bSMatthew G. Knepley 
1204cc4c1da9SBarry Smith /*@
120519307e5cSMatthew G. Knepley   DMSwarmCreateGlobalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set
120619307e5cSMatthew G. Knepley 
120719307e5cSMatthew G. Knepley   Collective
120819307e5cSMatthew G. Knepley 
120919307e5cSMatthew G. Knepley   Input Parameters:
121019307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
121119307e5cSMatthew G. Knepley . Nf         - the number of fields
121219307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
121319307e5cSMatthew G. Knepley 
121419307e5cSMatthew G. Knepley   Output Parameter:
121519307e5cSMatthew G. Knepley . vec - the vector
121619307e5cSMatthew G. Knepley 
121719307e5cSMatthew G. Knepley   Level: beginner
121819307e5cSMatthew G. Knepley 
121919307e5cSMatthew G. Knepley   Notes:
122019307e5cSMatthew G. Knepley   The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromFields()`.
122119307e5cSMatthew G. Knepley 
122219307e5cSMatthew G. Knepley   This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateGlobalVectorFromField()`
122319307e5cSMatthew G. Knepley 
122419307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromFields()`
122519307e5cSMatthew G. Knepley @*/
DMSwarmCreateGlobalVectorFromFields(DM dm,PetscInt Nf,const char * fieldnames[],Vec * vec)122619307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
122719307e5cSMatthew G. Knepley {
122819307e5cSMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
122919307e5cSMatthew G. Knepley 
123019307e5cSMatthew G. Knepley   PetscFunctionBegin;
123119307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
123219307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec));
123319307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
123419307e5cSMatthew G. Knepley }
123519307e5cSMatthew G. Knepley 
123619307e5cSMatthew G. Knepley /*@
123719307e5cSMatthew G. Knepley   DMSwarmDestroyGlobalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set
123819307e5cSMatthew G. Knepley 
123919307e5cSMatthew G. Knepley   Collective
124019307e5cSMatthew G. Knepley 
124119307e5cSMatthew G. Knepley   Input Parameters:
124219307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
124319307e5cSMatthew G. Knepley . Nf         - the number of fields
124419307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
124519307e5cSMatthew G. Knepley 
124619307e5cSMatthew G. Knepley   Output Parameter:
124719307e5cSMatthew G. Knepley . vec - the vector
124819307e5cSMatthew G. Knepley 
124919307e5cSMatthew G. Knepley   Level: beginner
125019307e5cSMatthew G. Knepley 
125119307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
125219307e5cSMatthew G. Knepley @*/
DMSwarmDestroyGlobalVectorFromFields(DM dm,PetscInt Nf,const char * fieldnames[],Vec * vec)125319307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
125419307e5cSMatthew G. Knepley {
125519307e5cSMatthew G. Knepley   PetscFunctionBegin;
125619307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
125719307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec));
125819307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
125919307e5cSMatthew G. Knepley }
126019307e5cSMatthew G. Knepley 
126119307e5cSMatthew G. Knepley /*@
126219307e5cSMatthew G. Knepley   DMSwarmCreateLocalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set
126319307e5cSMatthew G. Knepley 
126419307e5cSMatthew G. Knepley   Collective
126519307e5cSMatthew G. Knepley 
126619307e5cSMatthew G. Knepley   Input Parameters:
126719307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
126819307e5cSMatthew G. Knepley . Nf         - the number of fields
126919307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
127019307e5cSMatthew G. Knepley 
127119307e5cSMatthew G. Knepley   Output Parameter:
127219307e5cSMatthew G. Knepley . vec - the vector
127319307e5cSMatthew G. Knepley 
127419307e5cSMatthew G. Knepley   Level: beginner
127519307e5cSMatthew G. Knepley 
127619307e5cSMatthew G. Knepley   Notes:
127719307e5cSMatthew G. Knepley   The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
127819307e5cSMatthew G. Knepley 
127919307e5cSMatthew G. Knepley   This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateLocalVectorFromField()`
128019307e5cSMatthew G. Knepley 
128119307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
128219307e5cSMatthew G. Knepley @*/
DMSwarmCreateLocalVectorFromFields(DM dm,PetscInt Nf,const char * fieldnames[],Vec * vec)128319307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
128419307e5cSMatthew G. Knepley {
128519307e5cSMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
128619307e5cSMatthew G. Knepley 
128719307e5cSMatthew G. Knepley   PetscFunctionBegin;
128819307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec));
128919307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
129019307e5cSMatthew G. Knepley }
129119307e5cSMatthew G. Knepley 
129219307e5cSMatthew G. Knepley /*@
129319307e5cSMatthew G. Knepley   DMSwarmDestroyLocalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set
129419307e5cSMatthew G. Knepley 
129519307e5cSMatthew G. Knepley   Collective
129619307e5cSMatthew G. Knepley 
129719307e5cSMatthew G. Knepley   Input Parameters:
129819307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
129919307e5cSMatthew G. Knepley . Nf         - the number of fields
130019307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
130119307e5cSMatthew G. Knepley 
130219307e5cSMatthew G. Knepley   Output Parameter:
130319307e5cSMatthew G. Knepley . vec - the vector
130419307e5cSMatthew G. Knepley 
130519307e5cSMatthew G. Knepley   Level: beginner
130619307e5cSMatthew G. Knepley 
130719307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromFields()`
130819307e5cSMatthew G. Knepley @*/
DMSwarmDestroyLocalVectorFromFields(DM dm,PetscInt Nf,const char * fieldnames[],Vec * vec)130919307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
131019307e5cSMatthew G. Knepley {
131119307e5cSMatthew G. Knepley   PetscFunctionBegin;
131219307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
131319307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec));
131419307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
131519307e5cSMatthew G. Knepley }
131619307e5cSMatthew G. Knepley 
131719307e5cSMatthew G. Knepley /*@
131820f4b53cSBarry Smith   DMSwarmInitializeFieldRegister - Initiates the registration of fields to a `DMSWARM`
1319d3a51819SDave May 
132020f4b53cSBarry Smith   Collective
1321d3a51819SDave May 
132260225df5SJacob Faibussowitsch   Input Parameter:
132320f4b53cSBarry Smith . dm - a `DMSWARM`
1324d3a51819SDave May 
1325d3a51819SDave May   Level: beginner
1326d3a51819SDave May 
132720f4b53cSBarry Smith   Note:
132820f4b53cSBarry Smith   After all fields have been registered, you must call `DMSwarmFinalizeFieldRegister()`.
1329d3a51819SDave May 
133020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
1331db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1332d3a51819SDave May @*/
DMSwarmInitializeFieldRegister(DM dm)1333d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
1334d71ae5a4SJacob Faibussowitsch {
13355f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
13363454631fSDave May 
1337521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1338cc651181SDave May   if (!swarm->field_registration_initialized) {
13395f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
1340da81f932SPierre Jolivet     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifier */
13419566063dSJacob Faibussowitsch     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT));  /* used for communication */
1342cc651181SDave May   }
13433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13445f50eb2eSDave May }
13455f50eb2eSDave May 
134674d0cae8SMatthew G. Knepley /*@
134720f4b53cSBarry Smith   DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a `DMSWARM`
1348d3a51819SDave May 
134920f4b53cSBarry Smith   Collective
1350d3a51819SDave May 
135160225df5SJacob Faibussowitsch   Input Parameter:
135220f4b53cSBarry Smith . dm - a `DMSWARM`
1353d3a51819SDave May 
1354d3a51819SDave May   Level: beginner
1355d3a51819SDave May 
135620f4b53cSBarry Smith   Note:
135720f4b53cSBarry Smith   After `DMSwarmFinalizeFieldRegister()` has been called, no new fields can be defined on the `DMSWARM`.
1358d3a51819SDave May 
135920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
1360db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1361d3a51819SDave May @*/
DMSwarmFinalizeFieldRegister(DM dm)1362d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
1363d71ae5a4SJacob Faibussowitsch {
13645f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
13656845f8f5SDave May 
1366521f74f9SMatthew G. Knepley   PetscFunctionBegin;
136748a46eb9SPierre Jolivet   if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db));
1368f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
13693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13705f50eb2eSDave May }
13715f50eb2eSDave May 
137274d0cae8SMatthew G. Knepley /*@
137320f4b53cSBarry Smith   DMSwarmSetLocalSizes - Sets the length of all registered fields on the `DMSWARM`
1374d3a51819SDave May 
137520f4b53cSBarry Smith   Not Collective
1376d3a51819SDave May 
137760225df5SJacob Faibussowitsch   Input Parameters:
1378fca3fa51SMatthew G. Knepley + sw     - a `DMSWARM`
1379d3a51819SDave May . nlocal - the length of each registered field
138062741f57SDave May - buffer - the length of the buffer used to efficient dynamic re-sizing
1381d3a51819SDave May 
1382d3a51819SDave May   Level: beginner
1383d3a51819SDave May 
138420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`
1385d3a51819SDave May @*/
DMSwarmSetLocalSizes(DM sw,PetscInt nlocal,PetscInt buffer)1386fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmSetLocalSizes(DM sw, PetscInt nlocal, PetscInt buffer)
1387d71ae5a4SJacob Faibussowitsch {
1388fca3fa51SMatthew G. Knepley   DM_Swarm   *swarm = (DM_Swarm *)sw->data;
1389fca3fa51SMatthew G. Knepley   PetscMPIInt rank;
1390fca3fa51SMatthew G. Knepley   PetscInt   *rankval;
13915f50eb2eSDave May 
1392521f74f9SMatthew G. Knepley   PetscFunctionBegin;
13939566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0));
13949566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer));
13959566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0));
1396fca3fa51SMatthew G. Knepley 
1397fca3fa51SMatthew G. Knepley   // Initialize values in pid and rank placeholders
1398fca3fa51SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sw), &rank));
1399fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
1400fca3fa51SMatthew G. Knepley   for (PetscInt p = 0; p < nlocal; p++) rankval[p] = rank;
1401fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
1402fca3fa51SMatthew G. Knepley   /* TODO: [pid - use MPI_Scan] */
14033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14045f50eb2eSDave May }
14055f50eb2eSDave May 
140674d0cae8SMatthew G. Knepley /*@
140720f4b53cSBarry Smith   DMSwarmSetCellDM - Attaches a `DM` to a `DMSWARM`
1408d3a51819SDave May 
140920f4b53cSBarry Smith   Collective
1410d3a51819SDave May 
141160225df5SJacob Faibussowitsch   Input Parameters:
141219307e5cSMatthew G. Knepley + sw - a `DMSWARM`
141319307e5cSMatthew G. Knepley - dm - the `DM` to attach to the `DMSWARM`
1414d3a51819SDave May 
1415d3a51819SDave May   Level: beginner
1416d3a51819SDave May 
141720f4b53cSBarry Smith   Note:
141819307e5cSMatthew G. Knepley   The attached `DM` (dm) will be queried for point location and
141920f4b53cSBarry Smith   neighbor MPI-rank information if `DMSwarmMigrate()` is called.
1420d3a51819SDave May 
142120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()`
1422d3a51819SDave May @*/
DMSwarmSetCellDM(DM sw,DM dm)142319307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM sw, DM dm)
1424d71ae5a4SJacob Faibussowitsch {
142519307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
142619307e5cSMatthew G. Knepley   const char   *name;
142719307e5cSMatthew G. Knepley   char         *coordName;
1428d52c2f21SMatthew G. Knepley 
1429d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
1430d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
143119307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
143219307e5cSMatthew G. Knepley   PetscCall(PetscStrallocpy(DMSwarmPICField_coor, &coordName));
143319307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 1, (const char **)&coordName, &celldm));
143419307e5cSMatthew G. Knepley   PetscCall(PetscFree(coordName));
143519307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
143619307e5cSMatthew G. Knepley   PetscCall(DMSwarmAddCellDM(sw, celldm));
143719307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMDestroy(&celldm));
143819307e5cSMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(sw, name));
1439d52c2f21SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1440d52c2f21SMatthew G. Knepley }
1441d52c2f21SMatthew G. Knepley 
1442d52c2f21SMatthew G. Knepley /*@
144319307e5cSMatthew G. Knepley   DMSwarmGetCellDM - Fetches the active cell `DM`
1444d52c2f21SMatthew G. Knepley 
1445d52c2f21SMatthew G. Knepley   Collective
1446d52c2f21SMatthew G. Knepley 
1447d52c2f21SMatthew G. Knepley   Input Parameter:
1448d52c2f21SMatthew G. Knepley . sw - a `DMSWARM`
1449d52c2f21SMatthew G. Knepley 
145019307e5cSMatthew G. Knepley   Output Parameter:
145119307e5cSMatthew G. Knepley . dm - the active `DM` for the `DMSWARM`
145219307e5cSMatthew G. Knepley 
1453d52c2f21SMatthew G. Knepley   Level: beginner
1454d52c2f21SMatthew G. Knepley 
145519307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`
1456d52c2f21SMatthew G. Knepley @*/
DMSwarmGetCellDM(DM sw,DM * dm)145719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM sw, DM *dm)
1458d52c2f21SMatthew G. Knepley {
1459d52c2f21SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
146019307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
146119307e5cSMatthew G. Knepley 
146219307e5cSMatthew G. Knepley   PetscFunctionBegin;
1463fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
146419307e5cSMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)&celldm));
146519307e5cSMatthew G. Knepley   PetscCheck(celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "There is no cell DM named %s in this Swarm", swarm->activeCellDM);
146619307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetDM(celldm, dm));
146719307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
146819307e5cSMatthew G. Knepley }
146919307e5cSMatthew G. Knepley 
1470fca3fa51SMatthew G. Knepley /*@C
1471fca3fa51SMatthew G. Knepley   DMSwarmGetCellDMNames - Get the list of cell `DM` names
1472fca3fa51SMatthew G. Knepley 
1473fca3fa51SMatthew G. Knepley   Not collective
1474fca3fa51SMatthew G. Knepley 
1475fca3fa51SMatthew G. Knepley   Input Parameter:
1476fca3fa51SMatthew G. Knepley . sw - a `DMSWARM`
1477fca3fa51SMatthew G. Knepley 
1478fca3fa51SMatthew G. Knepley   Output Parameters:
1479fca3fa51SMatthew G. Knepley + Ndm     - the number of `DMSwarmCellDM` in the `DMSWARM`
1480fca3fa51SMatthew G. Knepley - celldms - the name of each `DMSwarmCellDM`
1481fca3fa51SMatthew G. Knepley 
1482fca3fa51SMatthew G. Knepley   Level: beginner
1483fca3fa51SMatthew G. Knepley 
1484fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmGetCellDMByName()`
1485fca3fa51SMatthew G. Knepley @*/
DMSwarmGetCellDMNames(DM sw,PetscInt * Ndm,const char ** celldms[])1486fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMNames(DM sw, PetscInt *Ndm, const char **celldms[])
1487fca3fa51SMatthew G. Knepley {
1488fca3fa51SMatthew G. Knepley   DM_Swarm       *swarm = (DM_Swarm *)sw->data;
1489fca3fa51SMatthew G. Knepley   PetscObjectList next  = swarm->cellDMs;
1490fca3fa51SMatthew G. Knepley   PetscInt        n     = 0;
1491fca3fa51SMatthew G. Knepley 
1492fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
1493fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1494fca3fa51SMatthew G. Knepley   PetscAssertPointer(Ndm, 2);
1495fca3fa51SMatthew G. Knepley   PetscAssertPointer(celldms, 3);
1496fca3fa51SMatthew G. Knepley   while (next) {
1497fca3fa51SMatthew G. Knepley     next = next->next;
1498fca3fa51SMatthew G. Knepley     ++n;
1499fca3fa51SMatthew G. Knepley   }
1500fca3fa51SMatthew G. Knepley   PetscCall(PetscMalloc1(n, celldms));
1501fca3fa51SMatthew G. Knepley   next = swarm->cellDMs;
1502fca3fa51SMatthew G. Knepley   n    = 0;
1503fca3fa51SMatthew G. Knepley   while (next) {
1504fca3fa51SMatthew G. Knepley     (*celldms)[n] = (const char *)next->obj->name;
1505fca3fa51SMatthew G. Knepley     next          = next->next;
1506fca3fa51SMatthew G. Knepley     ++n;
1507fca3fa51SMatthew G. Knepley   }
1508fca3fa51SMatthew G. Knepley   *Ndm = n;
1509fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1510fca3fa51SMatthew G. Knepley }
1511fca3fa51SMatthew G. Knepley 
151219307e5cSMatthew G. Knepley /*@
151319307e5cSMatthew G. Knepley   DMSwarmSetCellDMActive - Activates a cell `DM` for a `DMSWARM`
151419307e5cSMatthew G. Knepley 
151519307e5cSMatthew G. Knepley   Collective
151619307e5cSMatthew G. Knepley 
151719307e5cSMatthew G. Knepley   Input Parameters:
151819307e5cSMatthew G. Knepley + sw   - a `DMSWARM`
151919307e5cSMatthew G. Knepley - name - name of the cell `DM` to active for the `DMSWARM`
152019307e5cSMatthew G. Knepley 
152119307e5cSMatthew G. Knepley   Level: beginner
152219307e5cSMatthew G. Knepley 
152319307e5cSMatthew G. Knepley   Note:
152419307e5cSMatthew G. Knepley   The attached `DM` (dmcell) will be queried for point location and
152519307e5cSMatthew G. Knepley   neighbor MPI-rank information if `DMSwarmMigrate()` is called.
152619307e5cSMatthew G. Knepley 
152719307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
152819307e5cSMatthew G. Knepley @*/
DMSwarmSetCellDMActive(DM sw,const char name[])152919307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDMActive(DM sw, const char name[])
153019307e5cSMatthew G. Knepley {
153119307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
153219307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
1533d52c2f21SMatthew G. Knepley 
1534d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
1535d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
153619307e5cSMatthew G. Knepley   PetscCall(PetscInfo(sw, "Setting cell DM to %s\n", name));
153719307e5cSMatthew G. Knepley   PetscCall(PetscFree(swarm->activeCellDM));
153819307e5cSMatthew G. Knepley   PetscCall(PetscStrallocpy(name, (char **)&swarm->activeCellDM));
153919307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
154019307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1541d52c2f21SMatthew G. Knepley }
154219307e5cSMatthew G. Knepley 
154319307e5cSMatthew G. Knepley /*@
154419307e5cSMatthew G. Knepley   DMSwarmGetCellDMActive - Returns the active cell `DM` for a `DMSWARM`
154519307e5cSMatthew G. Knepley 
154619307e5cSMatthew G. Knepley   Collective
154719307e5cSMatthew G. Knepley 
154819307e5cSMatthew G. Knepley   Input Parameter:
154919307e5cSMatthew G. Knepley . sw - a `DMSWARM`
155019307e5cSMatthew G. Knepley 
155119307e5cSMatthew G. Knepley   Output Parameter:
155219307e5cSMatthew G. Knepley . celldm - the active `DMSwarmCellDM`
155319307e5cSMatthew G. Knepley 
155419307e5cSMatthew G. Knepley   Level: beginner
155519307e5cSMatthew G. Knepley 
155619307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
155719307e5cSMatthew G. Knepley @*/
DMSwarmGetCellDMActive(DM sw,DMSwarmCellDM * celldm)155819307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMActive(DM sw, DMSwarmCellDM *celldm)
155919307e5cSMatthew G. Knepley {
156019307e5cSMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
156119307e5cSMatthew G. Knepley 
156219307e5cSMatthew G. Knepley   PetscFunctionBegin;
156319307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1564fca3fa51SMatthew G. Knepley   PetscAssertPointer(celldm, 2);
156519307e5cSMatthew G. Knepley   PetscCheck(swarm->activeCellDM, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no active cell DM");
156619307e5cSMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)celldm));
1567fca3fa51SMatthew G. Knepley   PetscCheck(*celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no valid cell DM for %s", swarm->activeCellDM);
1568fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1569fca3fa51SMatthew G. Knepley }
1570fca3fa51SMatthew G. Knepley 
1571fca3fa51SMatthew G. Knepley /*@C
1572fca3fa51SMatthew G. Knepley   DMSwarmGetCellDMByName - Get a `DMSwarmCellDM` from its name
1573fca3fa51SMatthew G. Knepley 
1574fca3fa51SMatthew G. Knepley   Not collective
1575fca3fa51SMatthew G. Knepley 
1576fca3fa51SMatthew G. Knepley   Input Parameters:
1577fca3fa51SMatthew G. Knepley + sw   - a `DMSWARM`
1578fca3fa51SMatthew G. Knepley - name - the name
1579fca3fa51SMatthew G. Knepley 
1580fca3fa51SMatthew G. Knepley   Output Parameter:
1581fca3fa51SMatthew G. Knepley . celldm - the `DMSwarmCellDM`
1582fca3fa51SMatthew G. Knepley 
1583fca3fa51SMatthew G. Knepley   Level: beginner
1584fca3fa51SMatthew G. Knepley 
1585fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmGetCellDMNames()`
1586fca3fa51SMatthew G. Knepley @*/
DMSwarmGetCellDMByName(DM sw,const char name[],DMSwarmCellDM * celldm)1587fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMByName(DM sw, const char name[], DMSwarmCellDM *celldm)
1588fca3fa51SMatthew G. Knepley {
1589fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
1590fca3fa51SMatthew G. Knepley 
1591fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
1592fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1593fca3fa51SMatthew G. Knepley   PetscAssertPointer(name, 2);
1594fca3fa51SMatthew G. Knepley   PetscAssertPointer(celldm, 3);
1595fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, name, (PetscObject *)celldm));
1596fca3fa51SMatthew G. Knepley   PetscCheck(*celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no valid cell DM for %s", name);
159719307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
159819307e5cSMatthew G. Knepley }
159919307e5cSMatthew G. Knepley 
160019307e5cSMatthew G. Knepley /*@
160119307e5cSMatthew G. Knepley   DMSwarmAddCellDM - Adds a cell `DM` to the `DMSWARM`
160219307e5cSMatthew G. Knepley 
160319307e5cSMatthew G. Knepley   Collective
160419307e5cSMatthew G. Knepley 
160519307e5cSMatthew G. Knepley   Input Parameters:
160619307e5cSMatthew G. Knepley + sw     - a `DMSWARM`
160719307e5cSMatthew G. Knepley - celldm - the `DMSwarmCellDM`
160819307e5cSMatthew G. Knepley 
160919307e5cSMatthew G. Knepley   Level: beginner
161019307e5cSMatthew G. Knepley 
161119307e5cSMatthew G. Knepley   Note:
161219307e5cSMatthew G. Knepley   Cell DMs with the same name will share the cellid field
161319307e5cSMatthew G. Knepley 
161419307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmPushCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
161519307e5cSMatthew G. Knepley @*/
DMSwarmAddCellDM(DM sw,DMSwarmCellDM celldm)161619307e5cSMatthew G. Knepley PetscErrorCode DMSwarmAddCellDM(DM sw, DMSwarmCellDM celldm)
161719307e5cSMatthew G. Knepley {
161819307e5cSMatthew G. Knepley   DM_Swarm   *swarm = (DM_Swarm *)sw->data;
161919307e5cSMatthew G. Knepley   const char *name;
162019307e5cSMatthew G. Knepley   PetscInt    dim;
162119307e5cSMatthew G. Knepley   PetscBool   flg;
162219307e5cSMatthew G. Knepley   MPI_Comm    comm;
162319307e5cSMatthew G. Knepley 
162419307e5cSMatthew G. Knepley   PetscFunctionBegin;
162519307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
162619307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
162719307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(celldm, DMSWARMCELLDM_CLASSID, 2);
162819307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
162919307e5cSMatthew G. Knepley   PetscCall(PetscObjectListAdd(&swarm->cellDMs, name, (PetscObject)celldm));
163019307e5cSMatthew G. Knepley   PetscCall(DMGetDimension(sw, &dim));
163119307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nfc; ++f) {
163219307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataFieldStringInList(celldm->coordFields[f], swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg));
163319307e5cSMatthew G. Knepley     if (!flg) {
163419307e5cSMatthew G. Knepley       PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->coordFields[f], dim, PETSC_DOUBLE));
163519307e5cSMatthew G. Knepley     } else {
163619307e5cSMatthew G. Knepley       PetscDataType dt;
163719307e5cSMatthew G. Knepley       PetscInt      bs;
163819307e5cSMatthew G. Knepley 
163919307e5cSMatthew G. Knepley       PetscCall(DMSwarmGetFieldInfo(sw, celldm->coordFields[f], &bs, &dt));
164019307e5cSMatthew 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);
164119307e5cSMatthew G. Knepley       PetscCheck(dt == PETSC_DOUBLE, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s has datatype %s != PETSC_DOUBLE", celldm->coordFields[f], PetscDataTypes[dt]);
164219307e5cSMatthew G. Knepley     }
164319307e5cSMatthew G. Knepley   }
164419307e5cSMatthew G. Knepley   // Assume that DMs with the same name share the cellid field
164519307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataFieldStringInList(celldm->cellid, swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg));
164619307e5cSMatthew G. Knepley   if (!flg) {
164719307e5cSMatthew G. Knepley     PetscBool   isShell, isDummy;
164819307e5cSMatthew G. Knepley     const char *name;
164919307e5cSMatthew G. Knepley 
165019307e5cSMatthew G. Knepley     // Allow dummy DMSHELL (I don't think we should support this mode)
165119307e5cSMatthew G. Knepley     PetscCall(PetscObjectTypeCompare((PetscObject)celldm->dm, DMSHELL, &isShell));
165219307e5cSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)celldm->dm, &name));
165319307e5cSMatthew G. Knepley     PetscCall(PetscStrcmp(name, "dummy", &isDummy));
165419307e5cSMatthew G. Knepley     if (!isShell || !isDummy) PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->cellid, 1, PETSC_INT));
165519307e5cSMatthew G. Knepley   }
165619307e5cSMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(sw, name));
16573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1658fe39f135SDave May }
1659fe39f135SDave May 
166074d0cae8SMatthew G. Knepley /*@
1661d5b43468SJose E. Roman   DMSwarmGetLocalSize - Retrieves the local length of fields registered
1662d3a51819SDave May 
166320f4b53cSBarry Smith   Not Collective
1664d3a51819SDave May 
166560225df5SJacob Faibussowitsch   Input Parameter:
166620f4b53cSBarry Smith . dm - a `DMSWARM`
1667d3a51819SDave May 
166860225df5SJacob Faibussowitsch   Output Parameter:
1669d3a51819SDave May . nlocal - the length of each registered field
1670d3a51819SDave May 
1671d3a51819SDave May   Level: beginner
1672d3a51819SDave May 
167320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()`
1674d3a51819SDave May @*/
DMSwarmGetLocalSize(DM dm,PetscInt * nlocal)1675d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal)
1676d71ae5a4SJacob Faibussowitsch {
1677dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1678dcf43ee8SDave May 
1679521f74f9SMatthew G. Knepley   PetscFunctionBegin;
16809566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL));
16813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1682dcf43ee8SDave May }
1683dcf43ee8SDave May 
168474d0cae8SMatthew G. Knepley /*@
1685d5b43468SJose E. Roman   DMSwarmGetSize - Retrieves the total length of fields registered
1686d3a51819SDave May 
168720f4b53cSBarry Smith   Collective
1688d3a51819SDave May 
168960225df5SJacob Faibussowitsch   Input Parameter:
169020f4b53cSBarry Smith . dm - a `DMSWARM`
1691d3a51819SDave May 
169260225df5SJacob Faibussowitsch   Output Parameter:
1693d3a51819SDave May . n - the total length of each registered field
1694d3a51819SDave May 
1695d3a51819SDave May   Level: beginner
1696d3a51819SDave May 
1697d3a51819SDave May   Note:
169820f4b53cSBarry Smith   This calls `MPI_Allreduce()` upon each call (inefficient but safe)
1699d3a51819SDave May 
170020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()`
1701d3a51819SDave May @*/
DMSwarmGetSize(DM dm,PetscInt * n)1702d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n)
1703d71ae5a4SJacob Faibussowitsch {
1704dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
17055627991aSBarry Smith   PetscInt  nlocal;
1706dcf43ee8SDave May 
1707521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17089566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1709462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
17103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1711dcf43ee8SDave May }
1712dcf43ee8SDave May 
1713ce78bad3SBarry Smith /*@C
171420f4b53cSBarry Smith   DMSwarmRegisterPetscDatatypeField - Register a field to a `DMSWARM` with a native PETSc data type
1715d3a51819SDave May 
171620f4b53cSBarry Smith   Collective
1717d3a51819SDave May 
171860225df5SJacob Faibussowitsch   Input Parameters:
171920f4b53cSBarry Smith + dm        - a `DMSWARM`
1720d3a51819SDave May . fieldname - the textual name to identify this field
1721d3a51819SDave May . blocksize - the number of each data type
172220f4b53cSBarry Smith - type      - a valid PETSc data type (`PETSC_CHAR`, `PETSC_SHORT`, `PETSC_INT`, `PETSC_FLOAT`, `PETSC_REAL`, `PETSC_LONG`)
1723d3a51819SDave May 
1724d3a51819SDave May   Level: beginner
1725d3a51819SDave May 
1726d3a51819SDave May   Notes:
17278b8a3813SDave May   The textual name for each registered field must be unique.
1728d3a51819SDave May 
172920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1730d3a51819SDave May @*/
DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)1731d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type)
1732d71ae5a4SJacob Faibussowitsch {
1733b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1734b62e03f8SDave May   size_t    size;
1735b62e03f8SDave May 
1736521f74f9SMatthew G. Knepley   PetscFunctionBegin;
173728b400f6SJacob Faibussowitsch   PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first");
173828b400f6SJacob Faibussowitsch   PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
17395f50eb2eSDave May 
174008401ef6SPierre Jolivet   PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
174108401ef6SPierre Jolivet   PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
174208401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
174308401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
174408401ef6SPierre Jolivet   PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
1745b62e03f8SDave May 
17469566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &size));
1747b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
17489566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL));
174952c3ed93SDave May   {
175077048351SPatrick Sanan     DMSwarmDataField gfield;
175152c3ed93SDave May 
17529566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
17539566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
175452c3ed93SDave May   }
1755b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = type;
17563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1757b62e03f8SDave May }
1758b62e03f8SDave May 
1759d3a51819SDave May /*@C
176020f4b53cSBarry Smith   DMSwarmRegisterUserStructField - Register a user defined struct to a `DMSWARM`
1761d3a51819SDave May 
176220f4b53cSBarry Smith   Collective
1763d3a51819SDave May 
176460225df5SJacob Faibussowitsch   Input Parameters:
176520f4b53cSBarry Smith + dm        - a `DMSWARM`
1766d3a51819SDave May . fieldname - the textual name to identify this field
176762741f57SDave May - size      - the size in bytes of the user struct of each data type
1768d3a51819SDave May 
1769d3a51819SDave May   Level: beginner
1770d3a51819SDave May 
177120f4b53cSBarry Smith   Note:
17728b8a3813SDave May   The textual name for each registered field must be unique.
1773d3a51819SDave May 
177420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()`
1775d3a51819SDave May @*/
DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)1776d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size)
1777d71ae5a4SJacob Faibussowitsch {
1778b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1779b62e03f8SDave May 
1780521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17819566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL));
1782b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT;
17833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1784b62e03f8SDave May }
1785b62e03f8SDave May 
1786d3a51819SDave May /*@C
178720f4b53cSBarry Smith   DMSwarmRegisterUserDatatypeField - Register a user defined data type to a `DMSWARM`
1788d3a51819SDave May 
178920f4b53cSBarry Smith   Collective
1790d3a51819SDave May 
179160225df5SJacob Faibussowitsch   Input Parameters:
179220f4b53cSBarry Smith + dm        - a `DMSWARM`
1793d3a51819SDave May . fieldname - the textual name to identify this field
1794d3a51819SDave May . size      - the size in bytes of the user data type
179562741f57SDave May - blocksize - the number of each data type
1796d3a51819SDave May 
1797d3a51819SDave May   Level: beginner
1798d3a51819SDave May 
179920f4b53cSBarry Smith   Note:
18008b8a3813SDave May   The textual name for each registered field must be unique.
1801d3a51819SDave May 
180242747ad1SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()`
1803d3a51819SDave May @*/
DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)1804d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize)
1805d71ae5a4SJacob Faibussowitsch {
1806b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1807b62e03f8SDave May 
1808521f74f9SMatthew G. Knepley   PetscFunctionBegin;
18099566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL));
1810320740a0SDave May   {
181177048351SPatrick Sanan     DMSwarmDataField gfield;
1812320740a0SDave May 
18139566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
18149566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
1815320740a0SDave May   }
1816b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
18173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1818b62e03f8SDave May }
1819b62e03f8SDave May 
1820d3a51819SDave May /*@C
1821d3a51819SDave May   DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1822d3a51819SDave May 
1823cc4c1da9SBarry Smith   Not Collective, No Fortran Support
1824d3a51819SDave May 
182560225df5SJacob Faibussowitsch   Input Parameters:
182620f4b53cSBarry Smith + dm        - a `DMSWARM`
182762741f57SDave May - fieldname - the textual name to identify this field
1828d3a51819SDave May 
182960225df5SJacob Faibussowitsch   Output Parameters:
183062741f57SDave May + blocksize - the number of each data type
1831d3a51819SDave May . type      - the data type
183262741f57SDave May - data      - pointer to raw array
1833d3a51819SDave May 
1834d3a51819SDave May   Level: beginner
1835d3a51819SDave May 
1836d3a51819SDave May   Notes:
183720f4b53cSBarry Smith   The array must be returned using a matching call to `DMSwarmRestoreField()`.
1838d3a51819SDave May 
1839ce78bad3SBarry Smith   Fortran Note:
1840ce78bad3SBarry Smith   Only works for `type` of `PETSC_SCALAR`
1841ce78bad3SBarry Smith 
184220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreField()`
1843d3a51819SDave May @*/
DMSwarmGetField(DM dm,const char fieldname[],PetscInt * blocksize,PetscDataType * type,void ** data)1844ce78bad3SBarry Smith PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) PeNS
1845d71ae5a4SJacob Faibussowitsch {
1846b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
184777048351SPatrick Sanan   DMSwarmDataField gfield;
1848b62e03f8SDave May 
1849521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1850ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
18519566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
18529566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
18539566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetAccess(gfield));
18549566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetEntries(gfield, data));
1855ad540459SPierre Jolivet   if (blocksize) *blocksize = gfield->bs;
1856ad540459SPierre Jolivet   if (type) *type = gfield->petsc_type;
18573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1858b62e03f8SDave May }
1859b62e03f8SDave May 
1860d3a51819SDave May /*@C
1861d3a51819SDave May   DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1862d3a51819SDave May 
1863ce78bad3SBarry Smith   Not Collective
1864d3a51819SDave May 
186560225df5SJacob Faibussowitsch   Input Parameters:
186620f4b53cSBarry Smith + dm        - a `DMSWARM`
186762741f57SDave May - fieldname - the textual name to identify this field
1868d3a51819SDave May 
186960225df5SJacob Faibussowitsch   Output Parameters:
187062741f57SDave May + blocksize - the number of each data type
1871d3a51819SDave May . type      - the data type
187262741f57SDave May - data      - pointer to raw array
1873d3a51819SDave May 
1874d3a51819SDave May   Level: beginner
1875d3a51819SDave May 
1876d3a51819SDave May   Notes:
187720f4b53cSBarry Smith   The user must call `DMSwarmGetField()` prior to calling `DMSwarmRestoreField()`.
1878d3a51819SDave May 
1879ce78bad3SBarry Smith   Fortran Note:
1880ce78bad3SBarry Smith   Only works for `type` of `PETSC_SCALAR`
1881ce78bad3SBarry Smith 
188220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetField()`
1883d3a51819SDave May @*/
DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt * blocksize,PetscDataType * type,void ** data)1884ce78bad3SBarry Smith PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) PeNS
1885d71ae5a4SJacob Faibussowitsch {
1886b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
188777048351SPatrick Sanan   DMSwarmDataField gfield;
1888b62e03f8SDave May 
1889521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1890ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
18919566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
18929566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
1893b62e03f8SDave May   if (data) *data = NULL;
18943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1895b62e03f8SDave May }
1896b62e03f8SDave May 
DMSwarmGetFieldInfo(DM dm,const char fieldname[],PetscInt * blocksize,PetscDataType * type)18970bf7c1c5SMatthew G. Knepley PetscErrorCode DMSwarmGetFieldInfo(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type)
18980bf7c1c5SMatthew G. Knepley {
18990bf7c1c5SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
19000bf7c1c5SMatthew G. Knepley   DMSwarmDataField gfield;
19010bf7c1c5SMatthew G. Knepley 
19020bf7c1c5SMatthew G. Knepley   PetscFunctionBegin;
19030bf7c1c5SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
19040bf7c1c5SMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
19050bf7c1c5SMatthew G. Knepley   if (blocksize) *blocksize = gfield->bs;
19060bf7c1c5SMatthew G. Knepley   if (type) *type = gfield->petsc_type;
19070bf7c1c5SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
19080bf7c1c5SMatthew G. Knepley }
19090bf7c1c5SMatthew G. Knepley 
191074d0cae8SMatthew G. Knepley /*@
191120f4b53cSBarry Smith   DMSwarmAddPoint - Add space for one new point in the `DMSWARM`
1912d3a51819SDave May 
191320f4b53cSBarry Smith   Not Collective
1914d3a51819SDave May 
191560225df5SJacob Faibussowitsch   Input Parameter:
191620f4b53cSBarry Smith . dm - a `DMSWARM`
1917d3a51819SDave May 
1918d3a51819SDave May   Level: beginner
1919d3a51819SDave May 
1920d3a51819SDave May   Notes:
19218b8a3813SDave May   The new point will have all fields initialized to zero.
1922d3a51819SDave May 
192320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddNPoints()`
1924d3a51819SDave May @*/
DMSwarmAddPoint(DM dm)1925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddPoint(DM dm)
1926d71ae5a4SJacob Faibussowitsch {
1927cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1928cb1d1399SDave May 
1929521f74f9SMatthew G. Knepley   PetscFunctionBegin;
19309566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
19319566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
19329566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketAddPoint(swarm->db));
19339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
19343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1935cb1d1399SDave May }
1936cb1d1399SDave May 
193774d0cae8SMatthew G. Knepley /*@
193820f4b53cSBarry Smith   DMSwarmAddNPoints - Add space for a number of new points in the `DMSWARM`
1939d3a51819SDave May 
194020f4b53cSBarry Smith   Not Collective
1941d3a51819SDave May 
194260225df5SJacob Faibussowitsch   Input Parameters:
194320f4b53cSBarry Smith + dm      - a `DMSWARM`
194462741f57SDave May - npoints - the number of new points to add
1945d3a51819SDave May 
1946d3a51819SDave May   Level: beginner
1947d3a51819SDave May 
1948d3a51819SDave May   Notes:
19498b8a3813SDave May   The new point will have all fields initialized to zero.
1950d3a51819SDave May 
195120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddPoint()`
1952d3a51819SDave May @*/
DMSwarmAddNPoints(DM dm,PetscInt npoints)1953d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints)
1954d71ae5a4SJacob Faibussowitsch {
1955cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1956cb1d1399SDave May   PetscInt  nlocal;
1957cb1d1399SDave May 
1958521f74f9SMatthew G. Knepley   PetscFunctionBegin;
19599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
19609566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1961670292f5SMatthew Knepley   nlocal = PetscMax(nlocal, 0) + npoints;
19629566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
19639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
19643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1965cb1d1399SDave May }
1966cb1d1399SDave May 
196774d0cae8SMatthew G. Knepley /*@
196820f4b53cSBarry Smith   DMSwarmRemovePoint - Remove the last point from the `DMSWARM`
1969d3a51819SDave May 
197020f4b53cSBarry Smith   Not Collective
1971d3a51819SDave May 
197260225df5SJacob Faibussowitsch   Input Parameter:
197320f4b53cSBarry Smith . dm - a `DMSWARM`
1974d3a51819SDave May 
1975d3a51819SDave May   Level: beginner
1976d3a51819SDave May 
197720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePointAtIndex()`
1978d3a51819SDave May @*/
DMSwarmRemovePoint(DM dm)1979d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePoint(DM dm)
1980d71ae5a4SJacob Faibussowitsch {
1981cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1982cb1d1399SDave May 
1983521f74f9SMatthew G. Knepley   PetscFunctionBegin;
19849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
19859566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePoint(swarm->db));
19869566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
19873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1988cb1d1399SDave May }
1989cb1d1399SDave May 
199074d0cae8SMatthew G. Knepley /*@
199120f4b53cSBarry Smith   DMSwarmRemovePointAtIndex - Removes a specific point from the `DMSWARM`
1992d3a51819SDave May 
199320f4b53cSBarry Smith   Not Collective
1994d3a51819SDave May 
199560225df5SJacob Faibussowitsch   Input Parameters:
199620f4b53cSBarry Smith + dm  - a `DMSWARM`
199762741f57SDave May - idx - index of point to remove
1998d3a51819SDave May 
1999d3a51819SDave May   Level: beginner
2000d3a51819SDave May 
200120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()`
2002d3a51819SDave May @*/
DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)2003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx)
2004d71ae5a4SJacob Faibussowitsch {
2005cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2006cb1d1399SDave May 
2007521f74f9SMatthew G. Knepley   PetscFunctionBegin;
20089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
20099566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx));
20109566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
20113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2012cb1d1399SDave May }
2013b62e03f8SDave May 
201474d0cae8SMatthew G. Knepley /*@
201520f4b53cSBarry Smith   DMSwarmCopyPoint - Copy point pj to point pi in the `DMSWARM`
2016ba4fc9c6SDave May 
201720f4b53cSBarry Smith   Not Collective
2018ba4fc9c6SDave May 
201960225df5SJacob Faibussowitsch   Input Parameters:
202020f4b53cSBarry Smith + dm - a `DMSWARM`
2021ba4fc9c6SDave May . pi - the index of the point to copy
2022ba4fc9c6SDave May - pj - the point index where the copy should be located
2023ba4fc9c6SDave May 
2024ba4fc9c6SDave May   Level: beginner
2025ba4fc9c6SDave May 
202620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()`
2027ba4fc9c6SDave May @*/
DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)2028d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj)
2029d71ae5a4SJacob Faibussowitsch {
2030ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2031ba4fc9c6SDave May 
2032ba4fc9c6SDave May   PetscFunctionBegin;
20339566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
20349566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj));
20353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2036ba4fc9c6SDave May }
2037ba4fc9c6SDave May 
DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)203866976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points)
2039d71ae5a4SJacob Faibussowitsch {
2040521f74f9SMatthew G. Knepley   PetscFunctionBegin;
20419566063dSJacob Faibussowitsch   PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points));
20423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20433454631fSDave May }
20443454631fSDave May 
204574d0cae8SMatthew G. Knepley /*@
204620f4b53cSBarry Smith   DMSwarmMigrate - Relocates points defined in the `DMSWARM` to other MPI-ranks
2047d3a51819SDave May 
204820f4b53cSBarry Smith   Collective
2049d3a51819SDave May 
205060225df5SJacob Faibussowitsch   Input Parameters:
205120f4b53cSBarry Smith + dm                 - the `DMSWARM`
205262741f57SDave May - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
2053d3a51819SDave May 
2054d3a51819SDave May   Level: advanced
2055d3a51819SDave May 
205620f4b53cSBarry Smith   Notes:
205720f4b53cSBarry Smith   The `DM` will be modified to accommodate received points.
205820f4b53cSBarry Smith   If `remove_sent_points` is `PETSC_TRUE`, any points that were sent will be removed from the `DM`.
205920f4b53cSBarry Smith   Different styles of migration are supported. See `DMSwarmSetMigrateType()`.
206020f4b53cSBarry Smith 
206120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`
2062d3a51819SDave May @*/
DMSwarmMigrate(DM dm,PetscBool remove_sent_points)2063d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points)
2064d71ae5a4SJacob Faibussowitsch {
2065f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2066f0cdbbbaSDave May 
2067521f74f9SMatthew G. Knepley   PetscFunctionBegin;
20689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0));
2069f0cdbbbaSDave May   switch (swarm->migrate_type) {
2070d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_BASIC:
2071d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points));
2072d71ae5a4SJacob Faibussowitsch     break;
2073d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLNSCATTER:
2074d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points));
2075d71ae5a4SJacob Faibussowitsch     break;
2076d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLEXACT:
2077d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented");
2078d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_USER:
2079d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented");
2080d71ae5a4SJacob Faibussowitsch   default:
2081d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown");
2082f0cdbbbaSDave May   }
20839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0));
20849566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(dm));
20853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20863454631fSDave May }
20873454631fSDave May 
2088f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize);
2089f0cdbbbaSDave May 
2090d3a51819SDave May /*
2091d3a51819SDave May  DMSwarmCollectViewCreate
2092d3a51819SDave May 
2093d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
2094d3a51819SDave May 
2095d3a51819SDave May  Notes:
20968b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
2097d3a51819SDave May  they have finished computations associated with the collected points
2098d3a51819SDave May */
2099d3a51819SDave May 
210074d0cae8SMatthew G. Knepley /*@
2101d3a51819SDave May   DMSwarmCollectViewCreate - Applies a collection method and gathers points
210220f4b53cSBarry Smith   in neighbour ranks into the `DMSWARM`
2103d3a51819SDave May 
210420f4b53cSBarry Smith   Collective
2105d3a51819SDave May 
210660225df5SJacob Faibussowitsch   Input Parameter:
210720f4b53cSBarry Smith . dm - the `DMSWARM`
2108d3a51819SDave May 
2109d3a51819SDave May   Level: advanced
2110d3a51819SDave May 
211120f4b53cSBarry Smith   Notes:
211220f4b53cSBarry Smith   Users should call `DMSwarmCollectViewDestroy()` after
211320f4b53cSBarry Smith   they have finished computations associated with the collected points
21140764c050SBarry Smith 
211520f4b53cSBarry Smith   Different collect methods are supported. See `DMSwarmSetCollectType()`.
211620f4b53cSBarry Smith 
21170764c050SBarry Smith   Developer Note:
21180764c050SBarry Smith   Create and Destroy routines create new objects that can get destroyed, they do not change the state
21190764c050SBarry Smith   of the current object.
21200764c050SBarry Smith 
212120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()`
2122d3a51819SDave May @*/
DMSwarmCollectViewCreate(DM dm)2123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewCreate(DM dm)
2124d71ae5a4SJacob Faibussowitsch {
21252712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
21262712d1f2SDave May   PetscInt  ng;
21272712d1f2SDave May 
2128521f74f9SMatthew G. Knepley   PetscFunctionBegin;
212928b400f6SJacob Faibussowitsch   PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active");
21309566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &ng));
2131480eef7bSDave May   switch (swarm->collect_type) {
2132d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_BASIC:
2133d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng));
2134d71ae5a4SJacob Faibussowitsch     break;
2135d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_DMDABOUNDINGBOX:
2136d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
2137d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_GENERAL:
2138d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented");
2139d71ae5a4SJacob Faibussowitsch   default:
2140d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown");
2141480eef7bSDave May   }
2142480eef7bSDave May   swarm->collect_view_active       = PETSC_TRUE;
2143480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
21443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21452712d1f2SDave May }
21462712d1f2SDave May 
214774d0cae8SMatthew G. Knepley /*@
214820f4b53cSBarry Smith   DMSwarmCollectViewDestroy - Resets the `DMSWARM` to the size prior to calling `DMSwarmCollectViewCreate()`
2149d3a51819SDave May 
215020f4b53cSBarry Smith   Collective
2151d3a51819SDave May 
215260225df5SJacob Faibussowitsch   Input Parameters:
215320f4b53cSBarry Smith . dm - the `DMSWARM`
2154d3a51819SDave May 
2155d3a51819SDave May   Notes:
215620f4b53cSBarry Smith   Users should call `DMSwarmCollectViewCreate()` before this function is called.
2157d3a51819SDave May 
2158d3a51819SDave May   Level: advanced
2159d3a51819SDave May 
21600764c050SBarry Smith   Developer Note:
21610764c050SBarry Smith   Create and Destroy routines create new objects that can get destroyed, they do not change the state
21620764c050SBarry Smith   of the current object.
21630764c050SBarry Smith 
216420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()`
2165d3a51819SDave May @*/
DMSwarmCollectViewDestroy(DM dm)2166d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
2167d71ae5a4SJacob Faibussowitsch {
21682712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
21692712d1f2SDave May 
2170521f74f9SMatthew G. Knepley   PetscFunctionBegin;
217128b400f6SJacob Faibussowitsch   PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active");
21729566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1));
2173480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
21743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21752712d1f2SDave May }
21763454631fSDave May 
DMSwarmSetUpPIC(DM dm)217766976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmSetUpPIC(DM dm)
2178d71ae5a4SJacob Faibussowitsch {
2179f0cdbbbaSDave May   PetscInt dim;
2180f0cdbbbaSDave May 
2181521f74f9SMatthew G. Knepley   PetscFunctionBegin;
21829566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetNumSpecies(dm, 1));
21839566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
218463a3b9bcSJacob Faibussowitsch   PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
218563a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
21863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2187f0cdbbbaSDave May }
2188f0cdbbbaSDave May 
218974d0cae8SMatthew G. Knepley /*@
219031403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
219131403186SMatthew G. Knepley 
219220f4b53cSBarry Smith   Collective
219331403186SMatthew G. Knepley 
219460225df5SJacob Faibussowitsch   Input Parameters:
219520f4b53cSBarry Smith + dm  - the `DMSWARM`
219620f4b53cSBarry Smith - Npc - The number of particles per cell in the cell `DM`
219731403186SMatthew G. Knepley 
219831403186SMatthew G. Knepley   Level: intermediate
219931403186SMatthew G. Knepley 
220020f4b53cSBarry Smith   Notes:
220120f4b53cSBarry Smith   The user must use `DMSwarmSetCellDM()` to set the cell `DM` first. The particles are placed randomly inside each cell. If only
220220f4b53cSBarry Smith   one particle is in each cell, it is placed at the centroid.
220320f4b53cSBarry Smith 
220420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`
220531403186SMatthew G. Knepley @*/
DMSwarmSetPointCoordinatesRandom(DM dm,PetscInt Npc)2206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
2207d71ae5a4SJacob Faibussowitsch {
220831403186SMatthew G. Knepley   DM             cdm;
220919307e5cSMatthew G. Knepley   DMSwarmCellDM  celldm;
221031403186SMatthew G. Knepley   PetscRandom    rnd;
221131403186SMatthew G. Knepley   DMPolytopeType ct;
221231403186SMatthew G. Knepley   PetscBool      simplex;
221331403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
221419307e5cSMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p, Nfc;
221519307e5cSMatthew G. Knepley   const char   **coordFields;
221631403186SMatthew G. Knepley 
221731403186SMatthew G. Knepley   PetscFunctionBeginUser;
22189566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd));
22199566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0));
22209566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetType(rnd, PETSCRAND48));
222131403186SMatthew G. Knepley 
222219307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
222319307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
222419307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
22259566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
22269566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(cdm, &dim));
22279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd));
22289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(cdm, cStart, &ct));
222931403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
223031403186SMatthew G. Knepley 
22319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ));
223231403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
223319307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, coordFields[0], NULL, NULL, (void **)&coords));
223431403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
223531403186SMatthew G. Knepley     if (Npc == 1) {
22369566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL));
223731403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d];
223831403186SMatthew G. Knepley     } else {
22399566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */
224031403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
224131403186SMatthew G. Knepley         const PetscInt n   = c * Npc + p;
224231403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
224331403186SMatthew G. Knepley 
224431403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
22459566063dSJacob Faibussowitsch           PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d]));
224631403186SMatthew G. Knepley           sum += refcoords[d];
224731403186SMatthew G. Knepley         }
22489371c9d4SSatish Balay         if (simplex && sum > 0.0)
22499371c9d4SSatish Balay           for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum;
225031403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]);
225131403186SMatthew G. Knepley       }
225231403186SMatthew G. Knepley     }
225331403186SMatthew G. Knepley   }
225419307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, coordFields[0], NULL, NULL, (void **)&coords));
22559566063dSJacob Faibussowitsch   PetscCall(PetscFree5(centroid, xi0, v0, J, invJ));
22569566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rnd));
22573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
225831403186SMatthew G. Knepley }
225931403186SMatthew G. Knepley 
226031403186SMatthew G. Knepley /*@
2261fca3fa51SMatthew G. Knepley   DMSwarmGetType - Get particular flavor of `DMSWARM`
2262fca3fa51SMatthew G. Knepley 
2263fca3fa51SMatthew G. Knepley   Collective
2264fca3fa51SMatthew G. Knepley 
2265fca3fa51SMatthew G. Knepley   Input Parameter:
2266fca3fa51SMatthew G. Knepley . sw - the `DMSWARM`
2267fca3fa51SMatthew G. Knepley 
2268fca3fa51SMatthew G. Knepley   Output Parameter:
2269fca3fa51SMatthew G. Knepley . stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`)
2270fca3fa51SMatthew G. Knepley 
2271fca3fa51SMatthew G. Knepley   Level: advanced
2272fca3fa51SMatthew G. Knepley 
2273fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC`
2274fca3fa51SMatthew G. Knepley @*/
DMSwarmGetType(DM sw,DMSwarmType * stype)2275fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetType(DM sw, DMSwarmType *stype)
2276fca3fa51SMatthew G. Knepley {
2277fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
2278fca3fa51SMatthew G. Knepley 
2279fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2280fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
2281fca3fa51SMatthew G. Knepley   PetscAssertPointer(stype, 2);
2282fca3fa51SMatthew G. Knepley   *stype = swarm->swarm_type;
2283fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2284fca3fa51SMatthew G. Knepley }
2285fca3fa51SMatthew G. Knepley 
2286fca3fa51SMatthew G. Knepley /*@
228720f4b53cSBarry Smith   DMSwarmSetType - Set particular flavor of `DMSWARM`
2288d3a51819SDave May 
228920f4b53cSBarry Smith   Collective
2290d3a51819SDave May 
229160225df5SJacob Faibussowitsch   Input Parameters:
2292fca3fa51SMatthew G. Knepley + sw    - the `DMSWARM`
229320f4b53cSBarry Smith - stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`)
2294d3a51819SDave May 
2295d3a51819SDave May   Level: advanced
2296d3a51819SDave May 
229720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC`
2298d3a51819SDave May @*/
DMSwarmSetType(DM sw,DMSwarmType stype)2299fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM sw, DMSwarmType stype)
2300d71ae5a4SJacob Faibussowitsch {
2301fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
2302f0cdbbbaSDave May 
2303521f74f9SMatthew G. Knepley   PetscFunctionBegin;
2304fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
2305f0cdbbbaSDave May   swarm->swarm_type = stype;
2306fca3fa51SMatthew G. Knepley   if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(sw));
23073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2308f0cdbbbaSDave May }
2309f0cdbbbaSDave May 
DMSwarmCreateRemapDM_Private(DM sw,DM * rdm)2310fca3fa51SMatthew G. Knepley static PetscErrorCode DMSwarmCreateRemapDM_Private(DM sw, DM *rdm)
2311d71ae5a4SJacob Faibussowitsch {
2312fca3fa51SMatthew G. Knepley   PetscFE        fe;
2313fca3fa51SMatthew G. Knepley   DMPolytopeType ct;
2314fca3fa51SMatthew G. Knepley   PetscInt       dim, cStart;
2315fca3fa51SMatthew G. Knepley   const char    *prefix = "remap_";
2316fca3fa51SMatthew G. Knepley 
2317fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2318fca3fa51SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), rdm));
2319fca3fa51SMatthew G. Knepley   PetscCall(DMSetType(*rdm, DMPLEX));
2320fca3fa51SMatthew G. Knepley   PetscCall(DMPlexSetOptionsPrefix(*rdm, prefix));
2321fca3fa51SMatthew G. Knepley   PetscCall(DMSetFromOptions(*rdm));
2322fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*rdm, "remap"));
2323fca3fa51SMatthew G. Knepley   PetscCall(DMViewFromOptions(*rdm, NULL, "-dm_view"));
2324fca3fa51SMatthew G. Knepley 
2325fca3fa51SMatthew G. Knepley   PetscCall(DMGetDimension(*rdm, &dim));
2326fca3fa51SMatthew G. Knepley   PetscCall(DMPlexGetHeightStratum(*rdm, 0, &cStart, NULL));
2327fca3fa51SMatthew G. Knepley   PetscCall(DMPlexGetCellType(*rdm, cStart, &ct));
2328fca3fa51SMatthew G. Knepley   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, prefix, PETSC_DETERMINE, &fe));
2329fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)fe, "distribution"));
2330fca3fa51SMatthew G. Knepley   PetscCall(DMSetField(*rdm, 0, NULL, (PetscObject)fe));
2331fca3fa51SMatthew G. Knepley   PetscCall(DMCreateDS(*rdm));
2332fca3fa51SMatthew G. Knepley   PetscCall(PetscFEDestroy(&fe));
2333fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2334fca3fa51SMatthew G. Knepley }
2335fca3fa51SMatthew G. Knepley 
DMSetup_Swarm(DM sw)2336fca3fa51SMatthew G. Knepley static PetscErrorCode DMSetup_Swarm(DM sw)
2337fca3fa51SMatthew G. Knepley {
2338fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
23393454631fSDave May 
2340521f74f9SMatthew G. Knepley   PetscFunctionBegin;
23413ba16761SJacob Faibussowitsch   if (swarm->issetup) PetscFunctionReturn(PETSC_SUCCESS);
23423454631fSDave May   swarm->issetup = PETSC_TRUE;
23433454631fSDave May 
2344fca3fa51SMatthew G. Knepley   if (swarm->remap_type != DMSWARM_REMAP_NONE) {
2345fca3fa51SMatthew G. Knepley     DMSwarmCellDM celldm;
2346fca3fa51SMatthew G. Knepley     DM            rdm;
2347fca3fa51SMatthew G. Knepley     const char   *fieldnames[2]  = {DMSwarmPICField_coor, "velocity"};
2348fca3fa51SMatthew G. Knepley     const char   *vfieldnames[1] = {"w_q"};
2349fca3fa51SMatthew G. Knepley 
2350fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCreateRemapDM_Private(sw, &rdm));
2351fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMCreate(rdm, 1, vfieldnames, 2, fieldnames, &celldm));
2352fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmAddCellDM(sw, celldm));
2353fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMDestroy(&celldm));
2354fca3fa51SMatthew G. Knepley     PetscCall(DMDestroy(&rdm));
2355fca3fa51SMatthew G. Knepley   }
2356fca3fa51SMatthew G. Knepley 
2357f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
235819307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
2359f0cdbbbaSDave May 
2360fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
2361fca3fa51SMatthew G. Knepley     PetscCheck(celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "No active cell DM. DMSWARM_PIC requires you call DMSwarmSetCellDM() or DMSwarmAddCellDM()");
236219307e5cSMatthew G. Knepley     if (celldm->dm->ops->locatepointssubdomain) {
2363f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
2364fca3fa51SMatthew G. Knepley       PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n"));
2365f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
2366f0cdbbbaSDave May     } else {
2367f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
2368966bd95aSPierre Jolivet       PetscCheck(celldm->dm->ops->locatepoints, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
2369fca3fa51SMatthew G. Knepley       PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->LocatePoints\n"));
2370f0cdbbbaSDave May 
2371966bd95aSPierre Jolivet       PetscCheck(celldm->dm->ops->getneighbors, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
2372fca3fa51SMatthew G. Knepley       PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n"));
2373f0cdbbbaSDave May 
2374f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
2375f0cdbbbaSDave May     }
2376f0cdbbbaSDave May   }
2377f0cdbbbaSDave May 
2378fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmFinalizeFieldRegister(sw));
2379f0cdbbbaSDave May 
23803454631fSDave May   /* check some fields were registered */
2381fca3fa51SMatthew G. Knepley   PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()");
23823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23833454631fSDave May }
23843454631fSDave May 
DMDestroy_Swarm(DM dm)238566976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroy_Swarm(DM dm)
2386d71ae5a4SJacob Faibussowitsch {
238757795646SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
238857795646SDave May 
238957795646SDave May   PetscFunctionBegin;
23903ba16761SJacob Faibussowitsch   if (--swarm->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
239119307e5cSMatthew G. Knepley   PetscCall(PetscObjectListDestroy(&swarm->cellDMs));
239219307e5cSMatthew G. Knepley   PetscCall(PetscFree(swarm->activeCellDM));
23939566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&swarm->db));
23949566063dSJacob Faibussowitsch   PetscCall(PetscFree(swarm));
23953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
239657795646SDave May }
239757795646SDave May 
DMSwarmView_Draw(DM dm,PetscViewer viewer)239866976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
2399d71ae5a4SJacob Faibussowitsch {
2400a9ee3421SMatthew G. Knepley   DM            cdm;
240119307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
2402a9ee3421SMatthew G. Knepley   PetscDraw     draw;
240331403186SMatthew G. Knepley   PetscReal    *coords, oldPause, radius = 0.01;
240419307e5cSMatthew G. Knepley   PetscInt      Np, p, bs, Nfc;
240519307e5cSMatthew G. Knepley   const char  **coordFields;
2406a9ee3421SMatthew G. Knepley 
2407a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
24089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL));
24099566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
24109566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
24119566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetPause(draw, &oldPause));
24129566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, 0.0));
24139566063dSJacob Faibussowitsch   PetscCall(DMView(cdm, viewer));
24149566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, oldPause));
2415a9ee3421SMatthew G. Knepley 
241619307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
241719307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
241819307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
24199566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &Np));
242019307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, coordFields[0], &bs, NULL, (void **)&coords));
2421a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
2422a9ee3421SMatthew G. Knepley     const PetscInt i = p * bs;
2423a9ee3421SMatthew G. Knepley 
24249566063dSJacob Faibussowitsch     PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE));
2425a9ee3421SMatthew G. Knepley   }
242619307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, coordFields[0], &bs, NULL, (void **)&coords));
24279566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
24289566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
24299566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
24303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2431a9ee3421SMatthew G. Knepley }
2432a9ee3421SMatthew G. Knepley 
DMView_Swarm_Ascii(DM dm,PetscViewer viewer)2433d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer)
2434d71ae5a4SJacob Faibussowitsch {
24356a5217c0SMatthew G. Knepley   PetscViewerFormat format;
24366a5217c0SMatthew G. Knepley   PetscInt         *sizes;
24376a5217c0SMatthew G. Knepley   PetscInt          dim, Np, maxSize = 17;
24386a5217c0SMatthew G. Knepley   MPI_Comm          comm;
24396a5217c0SMatthew G. Knepley   PetscMPIInt       rank, size, p;
244019307e5cSMatthew G. Knepley   const char       *name, *cellid;
24416a5217c0SMatthew G. Knepley 
24426a5217c0SMatthew G. Knepley   PetscFunctionBegin;
24436a5217c0SMatthew G. Knepley   PetscCall(PetscViewerGetFormat(viewer, &format));
24446a5217c0SMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
24456a5217c0SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dm, &Np));
24466a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
24476a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
24486a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
24496a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
245063a3b9bcSJacob Faibussowitsch   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
245163a3b9bcSJacob Faibussowitsch   else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
24526a5217c0SMatthew G. Knepley   if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes));
24536a5217c0SMatthew G. Knepley   else PetscCall(PetscCalloc1(3, &sizes));
24546a5217c0SMatthew G. Knepley   if (size < maxSize) {
24556a5217c0SMatthew G. Knepley     PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
24566a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of particles per rank:"));
24576a5217c0SMatthew G. Knepley     for (p = 0; p < size; ++p) {
24586a5217c0SMatthew G. Knepley       if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]));
24596a5217c0SMatthew G. Knepley     }
24606a5217c0SMatthew G. Knepley   } else {
24616a5217c0SMatthew G. Knepley     PetscInt locMinMax[2] = {Np, Np};
24626a5217c0SMatthew G. Knepley 
24636a5217c0SMatthew G. Knepley     PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
24646a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
24656a5217c0SMatthew G. Knepley   }
24666a5217c0SMatthew G. Knepley   PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
24676a5217c0SMatthew G. Knepley   PetscCall(PetscFree(sizes));
24686a5217c0SMatthew G. Knepley   if (format == PETSC_VIEWER_ASCII_INFO) {
246919307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
24706a5217c0SMatthew G. Knepley     PetscInt     *cell;
24716a5217c0SMatthew G. Knepley 
24726a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells containing each particle:\n"));
24736a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
247419307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
247519307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMGetCellID(celldm, &cellid));
247619307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&cell));
247763a3b9bcSJacob Faibussowitsch     for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  p%d: %" PetscInt_FMT "\n", p, cell[p]));
24786a5217c0SMatthew G. Knepley     PetscCall(PetscViewerFlush(viewer));
24796a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
248019307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&cell));
24816a5217c0SMatthew G. Knepley   }
24823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24836a5217c0SMatthew G. Knepley }
24846a5217c0SMatthew G. Knepley 
DMView_Swarm(DM dm,PetscViewer viewer)248566976f2fSJacob Faibussowitsch static PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
2486d71ae5a4SJacob Faibussowitsch {
24875f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
24889f196a02SMartin Diehl   PetscBool isascii, ibinary, isvtk, isdraw, ispython;
24895627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
24905627991aSBarry Smith   PetscBool ishdf5;
24915627991aSBarry Smith #endif
24925f50eb2eSDave May 
24935f50eb2eSDave May   PetscFunctionBegin;
24945f50eb2eSDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24955f50eb2eSDave May   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24969f196a02SMartin Diehl   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
24979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
24989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
24995627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
25009566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25015627991aSBarry Smith #endif
25029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
25034fc69c0aSMatthew G. Knepley   PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython));
25049f196a02SMartin Diehl   if (isascii) {
25056a5217c0SMatthew G. Knepley     PetscViewerFormat format;
25066a5217c0SMatthew G. Knepley 
25076a5217c0SMatthew G. Knepley     PetscCall(PetscViewerGetFormat(viewer, &format));
25086a5217c0SMatthew G. Knepley     switch (format) {
2509d71ae5a4SJacob Faibussowitsch     case PETSC_VIEWER_ASCII_INFO_DETAIL:
2510d71ae5a4SJacob Faibussowitsch       PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT));
2511d71ae5a4SJacob Faibussowitsch       break;
2512d71ae5a4SJacob Faibussowitsch     default:
2513d71ae5a4SJacob Faibussowitsch       PetscCall(DMView_Swarm_Ascii(dm, viewer));
25146a5217c0SMatthew G. Knepley     }
2515f7d195e4SLawrence Mitchell   } else {
25165f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
251748a46eb9SPierre Jolivet     if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer));
25185f50eb2eSDave May #endif
251948a46eb9SPierre Jolivet     if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer));
25204fc69c0aSMatthew G. Knepley     if (ispython) PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)dm));
2521f7d195e4SLawrence Mitchell   }
25223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25235f50eb2eSDave May }
25245f50eb2eSDave May 
2525cc4c1da9SBarry Smith /*@
252620f4b53cSBarry Smith   DMSwarmGetCellSwarm - Extracts a single cell from the `DMSWARM` object, returns it as a single cell `DMSWARM`.
252720f4b53cSBarry 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.
2528d0c080abSJoseph Pusztay 
2529d0c080abSJoseph Pusztay   Noncollective
2530d0c080abSJoseph Pusztay 
253160225df5SJacob Faibussowitsch   Input Parameters:
253220f4b53cSBarry Smith + sw        - the `DMSWARM`
25335627991aSBarry Smith . cellID    - the integer id of the cell to be extracted and filtered
253420f4b53cSBarry Smith - cellswarm - The `DMSWARM` to receive the cell
2535d0c080abSJoseph Pusztay 
2536d0c080abSJoseph Pusztay   Level: beginner
2537d0c080abSJoseph Pusztay 
25385627991aSBarry Smith   Notes:
253920f4b53cSBarry Smith   This presently only supports `DMSWARM_PIC` type
25405627991aSBarry Smith 
254120f4b53cSBarry Smith   Should be restored with `DMSwarmRestoreCellSwarm()`
2542d0c080abSJoseph Pusztay 
254320f4b53cSBarry Smith   Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
254420f4b53cSBarry Smith 
254520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreCellSwarm()`
2546d0c080abSJoseph Pusztay @*/
DMSwarmGetCellSwarm(DM sw,PetscInt cellID,DM cellswarm)2547cc4c1da9SBarry Smith PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
2548d71ae5a4SJacob Faibussowitsch {
2549d0c080abSJoseph Pusztay   DM_Swarm   *original = (DM_Swarm *)sw->data;
2550d0c080abSJoseph Pusztay   DMLabel     label;
2551d0c080abSJoseph Pusztay   DM          dmc, subdmc;
2552d0c080abSJoseph Pusztay   PetscInt   *pids, particles, dim;
255319307e5cSMatthew G. Knepley   const char *name;
2554d0c080abSJoseph Pusztay 
2555d0c080abSJoseph Pusztay   PetscFunctionBegin;
2556d0c080abSJoseph Pusztay   /* Configure new swarm */
25579566063dSJacob Faibussowitsch   PetscCall(DMSetType(cellswarm, DMSWARM));
25589566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(sw, &dim));
25599566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(cellswarm, dim));
25609566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC));
2561d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
25629566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db));
25639566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
25649566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles));
25659566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
25669566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db));
25679566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
2568fe11354eSMatthew G. Knepley   PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids));
25699566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(sw, &dmc));
25709566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label));
25719566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(dmc, label));
25729566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cellID, 1));
257371f1c950SStefano Zampini   PetscCall(DMPlexFilter(dmc, label, 1, PETSC_FALSE, PETSC_FALSE, PetscObjectComm((PetscObject)dmc), NULL, &subdmc));
257419307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dmc, &name));
257519307e5cSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)subdmc, name));
25769566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetCellDM(cellswarm, subdmc));
25779566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
25783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2579d0c080abSJoseph Pusztay }
2580d0c080abSJoseph Pusztay 
2581cc4c1da9SBarry Smith /*@
258220f4b53cSBarry Smith   DMSwarmRestoreCellSwarm - Restores a `DMSWARM` object obtained with `DMSwarmGetCellSwarm()`. All fields are copied back into the parent swarm.
2583d0c080abSJoseph Pusztay 
2584d0c080abSJoseph Pusztay   Noncollective
2585d0c080abSJoseph Pusztay 
258660225df5SJacob Faibussowitsch   Input Parameters:
258720f4b53cSBarry Smith + sw        - the parent `DMSWARM`
2588d0c080abSJoseph Pusztay . cellID    - the integer id of the cell to be copied back into the parent swarm
2589d0c080abSJoseph Pusztay - cellswarm - the cell swarm object
2590d0c080abSJoseph Pusztay 
2591d0c080abSJoseph Pusztay   Level: beginner
2592d0c080abSJoseph Pusztay 
25935627991aSBarry Smith   Note:
259420f4b53cSBarry Smith   This only supports `DMSWARM_PIC` types of `DMSWARM`s
2595d0c080abSJoseph Pusztay 
259620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetCellSwarm()`
2597d0c080abSJoseph Pusztay @*/
DMSwarmRestoreCellSwarm(DM sw,PetscInt cellID,DM cellswarm)2598cc4c1da9SBarry Smith PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
2599d71ae5a4SJacob Faibussowitsch {
2600d0c080abSJoseph Pusztay   DM        dmc;
2601d0c080abSJoseph Pusztay   PetscInt *pids, particles, p;
2602d0c080abSJoseph Pusztay 
2603d0c080abSJoseph Pusztay   PetscFunctionBegin;
26049566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
26059566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
26069566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
2607d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
260848a46eb9SPierre Jolivet   for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p]));
2609d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
26109566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(cellswarm, &dmc));
26119566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
2612fe11354eSMatthew G. Knepley   PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids));
26133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2614d0c080abSJoseph Pusztay }
2615d0c080abSJoseph Pusztay 
2616d52c2f21SMatthew G. Knepley /*@
2617d52c2f21SMatthew G. Knepley   DMSwarmComputeMoments - Compute the first three particle moments for a given field
2618d52c2f21SMatthew G. Knepley 
2619d52c2f21SMatthew G. Knepley   Noncollective
2620d52c2f21SMatthew G. Knepley 
2621d52c2f21SMatthew G. Knepley   Input Parameters:
2622d52c2f21SMatthew G. Knepley + sw         - the `DMSWARM`
2623d52c2f21SMatthew G. Knepley . coordinate - the coordinate field name
2624d52c2f21SMatthew G. Knepley - weight     - the weight field name
2625d52c2f21SMatthew G. Knepley 
2626d52c2f21SMatthew G. Knepley   Output Parameter:
2627d52c2f21SMatthew G. Knepley . moments - the field moments
2628d52c2f21SMatthew G. Knepley 
2629d52c2f21SMatthew G. Knepley   Level: intermediate
2630d52c2f21SMatthew G. Knepley 
2631d52c2f21SMatthew G. Knepley   Notes:
2632d52c2f21SMatthew G. Knepley   The `moments` array should be of length bs + 2, where bs is the block size of the coordinate field.
2633d52c2f21SMatthew G. Knepley 
2634d52c2f21SMatthew G. Knepley   The weight field must be a scalar, having blocksize 1.
2635d52c2f21SMatthew G. Knepley 
2636d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMPlexComputeMoments()`
2637d52c2f21SMatthew G. Knepley @*/
DMSwarmComputeMoments(DM sw,const char coordinate[],const char weight[],PetscReal moments[])2638d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmComputeMoments(DM sw, const char coordinate[], const char weight[], PetscReal moments[])
2639d52c2f21SMatthew G. Knepley {
2640d52c2f21SMatthew G. Knepley   const PetscReal *coords;
2641d52c2f21SMatthew G. Knepley   const PetscReal *w;
2642d52c2f21SMatthew G. Knepley   PetscReal       *mom;
2643d52c2f21SMatthew G. Knepley   PetscDataType    dtc, dtw;
2644d52c2f21SMatthew G. Knepley   PetscInt         bsc, bsw, Np;
2645d52c2f21SMatthew G. Knepley   MPI_Comm         comm;
2646d52c2f21SMatthew G. Knepley 
2647d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
2648d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
2649d52c2f21SMatthew G. Knepley   PetscAssertPointer(coordinate, 2);
2650d52c2f21SMatthew G. Knepley   PetscAssertPointer(weight, 3);
2651d52c2f21SMatthew G. Knepley   PetscAssertPointer(moments, 4);
2652d52c2f21SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
2653d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, coordinate, &bsc, &dtc, (void **)&coords));
2654d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, weight, &bsw, &dtw, (void **)&w));
2655d52c2f21SMatthew G. Knepley   PetscCheck(dtc == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s must be real, not %s", coordinate, PetscDataTypes[dtc]);
2656d52c2f21SMatthew G. Knepley   PetscCheck(dtw == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be real, not %s", weight, PetscDataTypes[dtw]);
2657d52c2f21SMatthew G. Knepley   PetscCheck(bsw == 1, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be a scalar, not blocksize %" PetscInt_FMT, weight, bsw);
2658d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(sw, &Np));
2659d52c2f21SMatthew G. Knepley   PetscCall(DMGetWorkArray(sw, bsc + 2, MPIU_REAL, &mom));
2660d52c2f21SMatthew G. Knepley   PetscCall(PetscArrayzero(mom, bsc + 2));
2661d52c2f21SMatthew G. Knepley   for (PetscInt p = 0; p < Np; ++p) {
2662d52c2f21SMatthew G. Knepley     const PetscReal *c  = &coords[p * bsc];
2663d52c2f21SMatthew G. Knepley     const PetscReal  wp = w[p];
2664d52c2f21SMatthew G. Knepley 
2665d52c2f21SMatthew G. Knepley     mom[0] += wp;
2666d52c2f21SMatthew G. Knepley     for (PetscInt d = 0; d < bsc; ++d) {
2667d52c2f21SMatthew G. Knepley       mom[d + 1] += wp * c[d];
2668d52c2f21SMatthew G. Knepley       mom[d + bsc + 1] += wp * PetscSqr(c[d]);
2669d52c2f21SMatthew G. Knepley     }
2670d52c2f21SMatthew G. Knepley   }
2671d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&coords));
2672d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w));
2673d52c2f21SMatthew G. Knepley   PetscCallMPI(MPIU_Allreduce(mom, moments, bsc + 2, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)sw)));
2674d52c2f21SMatthew G. Knepley   PetscCall(DMRestoreWorkArray(sw, bsc + 2, MPIU_REAL, &mom));
2675d0c080abSJoseph Pusztay   PetscFunctionReturn(PETSC_SUCCESS);
2676d0c080abSJoseph Pusztay }
2677d0c080abSJoseph Pusztay 
DMSetFromOptions_Swarm(DM dm,PetscOptionItems PetscOptionsObject)2678ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Swarm(DM dm, PetscOptionItems PetscOptionsObject)
2679fca3fa51SMatthew G. Knepley {
2680fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2681fca3fa51SMatthew G. Knepley 
2682fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2683fca3fa51SMatthew G. Knepley   PetscOptionsHeadBegin(PetscOptionsObject, "DMSwarm Options");
2684fca3fa51SMatthew G. Knepley   PetscCall(PetscOptionsEnum("-dm_swarm_remap_type", "Remap algorithm", "DMSwarmSetRemapType", DMSwarmRemapTypeNames, (PetscEnum)swarm->remap_type, (PetscEnum *)&swarm->remap_type, NULL));
2685fca3fa51SMatthew G. Knepley   PetscOptionsHeadEnd();
2686fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2687fca3fa51SMatthew G. Knepley }
2688fca3fa51SMatthew G. Knepley 
2689d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
2690d0c080abSJoseph Pusztay 
DMInitialize_Swarm(DM sw)2691d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Swarm(DM sw)
2692d71ae5a4SJacob Faibussowitsch {
2693d0c080abSJoseph Pusztay   PetscFunctionBegin;
2694d0c080abSJoseph Pusztay   sw->ops->view                     = DMView_Swarm;
2695d0c080abSJoseph Pusztay   sw->ops->load                     = NULL;
2696fca3fa51SMatthew G. Knepley   sw->ops->setfromoptions           = DMSetFromOptions_Swarm;
2697d0c080abSJoseph Pusztay   sw->ops->clone                    = DMClone_Swarm;
2698d0c080abSJoseph Pusztay   sw->ops->setup                    = DMSetup_Swarm;
2699d0c080abSJoseph Pusztay   sw->ops->createlocalsection       = NULL;
2700adc21957SMatthew G. Knepley   sw->ops->createsectionpermutation = NULL;
2701d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints = NULL;
2702d0c080abSJoseph Pusztay   sw->ops->createglobalvector       = DMCreateGlobalVector_Swarm;
2703d0c080abSJoseph Pusztay   sw->ops->createlocalvector        = DMCreateLocalVector_Swarm;
2704d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping  = NULL;
2705d0c080abSJoseph Pusztay   sw->ops->createfieldis            = NULL;
2706d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm       = NULL;
270799acd26cSksagiyam   sw->ops->createcellcoordinatedm   = NULL;
2708d0c080abSJoseph Pusztay   sw->ops->getcoloring              = NULL;
2709d0c080abSJoseph Pusztay   sw->ops->creatematrix             = DMCreateMatrix_Swarm;
2710d0c080abSJoseph Pusztay   sw->ops->createinterpolation      = NULL;
2711d0c080abSJoseph Pusztay   sw->ops->createinjection          = NULL;
2712d0c080abSJoseph Pusztay   sw->ops->createmassmatrix         = DMCreateMassMatrix_Swarm;
27131898fd5cSMatthew G. Knepley   sw->ops->creategradientmatrix     = DMCreateGradientMatrix_Swarm;
2714d0c080abSJoseph Pusztay   sw->ops->refine                   = NULL;
2715d0c080abSJoseph Pusztay   sw->ops->coarsen                  = NULL;
2716d0c080abSJoseph Pusztay   sw->ops->refinehierarchy          = NULL;
2717d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy         = NULL;
27189d50c5ebSMatthew G. Knepley   sw->ops->globaltolocalbegin       = DMGlobalToLocalBegin_Swarm;
27199d50c5ebSMatthew G. Knepley   sw->ops->globaltolocalend         = DMGlobalToLocalEnd_Swarm;
27209d50c5ebSMatthew G. Knepley   sw->ops->localtoglobalbegin       = DMLocalToGlobalBegin_Swarm;
27219d50c5ebSMatthew G. Knepley   sw->ops->localtoglobalend         = DMLocalToGlobalEnd_Swarm;
2722d0c080abSJoseph Pusztay   sw->ops->destroy                  = DMDestroy_Swarm;
2723d0c080abSJoseph Pusztay   sw->ops->createsubdm              = NULL;
2724d0c080abSJoseph Pusztay   sw->ops->getdimpoints             = NULL;
2725d0c080abSJoseph Pusztay   sw->ops->locatepoints             = NULL;
27269d50c5ebSMatthew G. Knepley   sw->ops->projectfieldlocal        = DMProjectFieldLocal_Swarm;
27273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2728d0c080abSJoseph Pusztay }
2729d0c080abSJoseph Pusztay 
DMClone_Swarm(DM dm,DM * newdm)2730d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm)
2731d71ae5a4SJacob Faibussowitsch {
2732d0c080abSJoseph Pusztay   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2733d0c080abSJoseph Pusztay 
2734d0c080abSJoseph Pusztay   PetscFunctionBegin;
2735d0c080abSJoseph Pusztay   swarm->refct++;
2736d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
27379566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM));
27389566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(*newdm));
27392e56dffeSJoe Pusztay   (*newdm)->dim = dm->dim;
27403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2741d0c080abSJoseph Pusztay }
2742d0c080abSJoseph Pusztay 
2743d3a51819SDave May /*MC
27440b4b7b1cSBarry Smith  DMSWARM = "swarm" - A `DM` object for particle methods, such as particle-in-cell (PIC), in which the underlying
27450b4b7b1cSBarry Smith            data is both (i) dynamic in length, (ii) and of arbitrary data type.
2746d3a51819SDave May 
274720f4b53cSBarry Smith  Level: intermediate
274820f4b53cSBarry Smith 
274920f4b53cSBarry Smith  Notes:
27500b4b7b1cSBarry Smith  User data can be represented by `DMSWARM` through a registering "fields" which are to be stored on particles.
275162741f57SDave May  To register a field, the user must provide;
275262741f57SDave May  (a) a unique name;
275362741f57SDave May  (b) the data type (or size in bytes);
275462741f57SDave May  (c) the block size of the data.
2755d3a51819SDave May 
2756d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
2757c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
275820f4b53cSBarry Smith .vb
275920f4b53cSBarry Smith     DMSwarmInitializeFieldRegister(dm)
276020f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
276120f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
276220f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
276320f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
276420f4b53cSBarry Smith     DMSwarmFinalizeFieldRegister(dm)
276520f4b53cSBarry Smith .ve
2766d3a51819SDave May 
276720f4b53cSBarry Smith  The fields represented by `DMSWARM` are dynamic and can be re-sized at any time.
27680b4b7b1cSBarry Smith  The only restriction imposed by `DMSWARM` is that all fields contain the same number of particles.
2769d3a51819SDave May 
2770d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
27715627991aSBarry Smith  between ranks.
2772d3a51819SDave May 
277320f4b53cSBarry Smith  `DMSWARM` supports the methods `DMCreateGlobalVector()` and `DMCreateLocalVector()`.
277420f4b53cSBarry Smith  As a `DMSWARM` may internally define and store values of different data types,
277520f4b53cSBarry Smith  before calling `DMCreateGlobalVector()` or `DMCreateLocalVector()`, the user must inform `DMSWARM` which
27760b4b7b1cSBarry Smith  fields should be used to define a `Vec` object via `DMSwarmVectorDefineField()`
2777c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
2778c215a47eSMatthew Knepley  compatible with different fields to be created.
2779d3a51819SDave May 
27800b4b7b1cSBarry Smith  A dual representation of fields in the `DMSWARM` and a Vec object is permitted via `DMSwarmCreateGlobalVectorFromField()`
27810b4b7b1cSBarry Smith  Here the data defining the field in the `DMSWARM` is shared with a `Vec`.
2782d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
278320f4b53cSBarry Smith  calls to `DMSwarmCreateGlobalVectorFromField()` and `DMSwarmDestroyGlobalVectorFromField()`.
278420f4b53cSBarry Smith  If the local size of the `DMSWARM` does not match the local size of the global vector
278520f4b53cSBarry Smith  when `DMSwarmDestroyGlobalVectorFromField()` is called, an error is thrown.
2786d3a51819SDave May 
27870b4b7b1cSBarry Smith  Additional high-level support is provided for Particle-In-Cell methods. Refer to `DMSwarmSetType()`.
278862741f57SDave May 
27890b4b7b1cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMType`, `DMCreate()`, `DMSetType()`, `DMSwarmSetType()`, `DMSwarmType`, `DMSwarmCreateGlobalVectorFromField()`,
27900b4b7b1cSBarry Smith          `DMCreateGlobalVector()`, `DMCreateLocalVector()`
2791d3a51819SDave May M*/
2792cc4c1da9SBarry Smith 
DMCreate_Swarm(DM dm)2793d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
2794d71ae5a4SJacob Faibussowitsch {
279557795646SDave May   DM_Swarm *swarm;
279657795646SDave May 
279757795646SDave May   PetscFunctionBegin;
279857795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27994dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&swarm));
2800f0cdbbbaSDave May   dm->data = swarm;
28019566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreate(&swarm->db));
28029566063dSJacob Faibussowitsch   PetscCall(DMSwarmInitializeFieldRegister(dm));
2803d52c2f21SMatthew G. Knepley   dm->dim                               = 0;
2804d0c080abSJoseph Pusztay   swarm->refct                          = 1;
28053454631fSDave May   swarm->issetup                        = PETSC_FALSE;
2806480eef7bSDave May   swarm->swarm_type                     = DMSWARM_BASIC;
2807480eef7bSDave May   swarm->migrate_type                   = DMSWARM_MIGRATE_BASIC;
2808480eef7bSDave May   swarm->collect_type                   = DMSWARM_COLLECT_BASIC;
280940c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
2810f0cdbbbaSDave May   swarm->collect_view_active            = PETSC_FALSE;
2811f0cdbbbaSDave May   swarm->collect_view_reset_nlocal      = -1;
28129566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(dm));
28132e956fe4SStefano Zampini   if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId));
28143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
281557795646SDave May }
281619307e5cSMatthew G. Knepley 
281719307e5cSMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
281819307e5cSMatthew G. Knepley    - Share the DM_Swarm structure
281919307e5cSMatthew G. Knepley */
DMSwarmReplace(DM dm,DM * ndm)282019307e5cSMatthew G. Knepley PetscErrorCode DMSwarmReplace(DM dm, DM *ndm)
282119307e5cSMatthew G. Knepley {
282219307e5cSMatthew G. Knepley   DM               dmNew = *ndm;
282319307e5cSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
282419307e5cSMatthew G. Knepley   PetscInt         dim;
282519307e5cSMatthew G. Knepley 
282619307e5cSMatthew G. Knepley   PetscFunctionBegin;
282719307e5cSMatthew G. Knepley   if (dm == dmNew) {
282819307e5cSMatthew G. Knepley     PetscCall(DMDestroy(ndm));
282919307e5cSMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
283019307e5cSMatthew G. Knepley   }
283119307e5cSMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
283219307e5cSMatthew G. Knepley   if (!dm->hdr.name) {
283319307e5cSMatthew G. Knepley     const char *name;
283419307e5cSMatthew G. Knepley 
283519307e5cSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)*ndm, &name));
283619307e5cSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
283719307e5cSMatthew G. Knepley   }
283819307e5cSMatthew G. Knepley   PetscCall(DMGetDimension(dmNew, &dim));
283919307e5cSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
284019307e5cSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
284119307e5cSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
284219307e5cSMatthew G. Knepley   PetscCall(DMDestroy_Swarm(dm));
284319307e5cSMatthew G. Knepley   PetscCall(DMInitialize_Swarm(dm));
284419307e5cSMatthew G. Knepley   dm->data = dmNew->data;
284519307e5cSMatthew G. Knepley   ((DM_Swarm *)dmNew->data)->refct++;
284619307e5cSMatthew G. Knepley   PetscCall(DMDestroy(ndm));
284719307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
284819307e5cSMatthew G. Knepley }
2849fca3fa51SMatthew G. Knepley 
2850fca3fa51SMatthew G. Knepley /*@
2851fca3fa51SMatthew G. Knepley   DMSwarmDuplicate - Creates a new `DMSWARM` with the same fields and cell `DM`s but no particles
2852fca3fa51SMatthew G. Knepley 
2853fca3fa51SMatthew G. Knepley   Collective
2854fca3fa51SMatthew G. Knepley 
2855fca3fa51SMatthew G. Knepley   Input Parameter:
2856fca3fa51SMatthew G. Knepley . sw - the `DMSWARM`
2857fca3fa51SMatthew G. Knepley 
2858fca3fa51SMatthew G. Knepley   Output Parameter:
2859fca3fa51SMatthew G. Knepley . nsw - the new `DMSWARM`
2860fca3fa51SMatthew G. Knepley 
2861fca3fa51SMatthew G. Knepley   Level: beginner
2862fca3fa51SMatthew G. Knepley 
2863fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCreate()`, `DMClone()`
2864fca3fa51SMatthew G. Knepley @*/
DMSwarmDuplicate(DM sw,DM * nsw)2865fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmDuplicate(DM sw, DM *nsw)
2866fca3fa51SMatthew G. Knepley {
2867fca3fa51SMatthew G. Knepley   DM_Swarm         *swarm = (DM_Swarm *)sw->data;
2868fca3fa51SMatthew G. Knepley   DMSwarmDataField *fields;
2869fca3fa51SMatthew G. Knepley   DMSwarmCellDM     celldm, ncelldm;
2870fca3fa51SMatthew G. Knepley   DMSwarmType       stype;
2871fca3fa51SMatthew G. Knepley   const char       *name, **celldmnames;
2872fca3fa51SMatthew G. Knepley   void             *ctx;
2873fca3fa51SMatthew G. Knepley   PetscInt          dim, Nf, Ndm;
2874fca3fa51SMatthew G. Knepley   PetscBool         flg;
2875fca3fa51SMatthew G. Knepley 
2876fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2877fca3fa51SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), nsw));
2878fca3fa51SMatthew G. Knepley   PetscCall(DMSetType(*nsw, DMSWARM));
2879fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)sw, &name));
2880fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*nsw, name));
2881fca3fa51SMatthew G. Knepley   PetscCall(DMGetDimension(sw, &dim));
2882fca3fa51SMatthew G. Knepley   PetscCall(DMSetDimension(*nsw, dim));
2883fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetType(sw, &stype));
2884fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmSetType(*nsw, stype));
2885fca3fa51SMatthew G. Knepley   PetscCall(DMGetApplicationContext(sw, &ctx));
2886fca3fa51SMatthew G. Knepley   PetscCall(DMSetApplicationContext(*nsw, ctx));
2887fca3fa51SMatthew G. Knepley 
2888fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetDMSwarmDataFields(swarm->db, &Nf, &fields));
2889fca3fa51SMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
2890fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmDataFieldStringInList(fields[f]->name, ((DM_Swarm *)(*nsw)->data)->db->nfields, (const DMSwarmDataField *)((DM_Swarm *)(*nsw)->data)->db->field, &flg));
2891fca3fa51SMatthew G. Knepley     if (!flg) PetscCall(DMSwarmRegisterPetscDatatypeField(*nsw, fields[f]->name, fields[f]->bs, fields[f]->petsc_type));
2892fca3fa51SMatthew G. Knepley   }
2893fca3fa51SMatthew G. Knepley 
2894fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetCellDMNames(sw, &Ndm, &celldmnames));
2895fca3fa51SMatthew G. Knepley   for (PetscInt c = 0; c < Ndm; ++c) {
2896fca3fa51SMatthew G. Knepley     DM           dm;
2897fca3fa51SMatthew G. Knepley     PetscInt     Ncf;
2898fca3fa51SMatthew G. Knepley     const char **coordfields, **fields;
2899fca3fa51SMatthew G. Knepley 
2900fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmGetCellDMByName(sw, celldmnames[c], &celldm));
2901fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMGetDM(celldm, &dm));
2902fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Ncf, &coordfields));
2903fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMGetFields(celldm, &Nf, &fields));
2904fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMCreate(dm, Nf, fields, Ncf, coordfields, &ncelldm));
2905fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmAddCellDM(*nsw, ncelldm));
2906fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMDestroy(&ncelldm));
2907fca3fa51SMatthew G. Knepley   }
2908fca3fa51SMatthew G. Knepley   PetscCall(PetscFree(celldmnames));
2909fca3fa51SMatthew G. Knepley 
2910fca3fa51SMatthew G. Knepley   PetscCall(DMSetFromOptions(*nsw));
2911fca3fa51SMatthew G. Knepley   PetscCall(DMSetUp(*nsw));
2912fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
2913fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
2914fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(*nsw, name));
2915fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2916fca3fa51SMatthew G. Knepley }
29179d50c5ebSMatthew G. Knepley 
DMLocalToGlobalBegin_Swarm(DM dm,Vec l,InsertMode mode,Vec g)29189d50c5ebSMatthew G. Knepley PetscErrorCode DMLocalToGlobalBegin_Swarm(DM dm, Vec l, InsertMode mode, Vec g)
29199d50c5ebSMatthew G. Knepley {
29209d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
29219d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
29229d50c5ebSMatthew G. Knepley }
29239d50c5ebSMatthew G. Knepley 
DMLocalToGlobalEnd_Swarm(DM dm,Vec l,InsertMode mode,Vec g)29249d50c5ebSMatthew G. Knepley PetscErrorCode DMLocalToGlobalEnd_Swarm(DM dm, Vec l, InsertMode mode, Vec g)
29259d50c5ebSMatthew G. Knepley {
29269d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
29279d50c5ebSMatthew G. Knepley   switch (mode) {
29289d50c5ebSMatthew G. Knepley   case INSERT_VALUES:
29299d50c5ebSMatthew G. Knepley     PetscCall(VecCopy(l, g));
29309d50c5ebSMatthew G. Knepley     break;
29319d50c5ebSMatthew G. Knepley   case ADD_VALUES:
29329d50c5ebSMatthew G. Knepley     PetscCall(VecAXPY(g, 1., l));
29339d50c5ebSMatthew G. Knepley     break;
29349d50c5ebSMatthew G. Knepley   default:
29359d50c5ebSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mode not supported: %d", mode);
29369d50c5ebSMatthew G. Knepley   }
29379d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
29389d50c5ebSMatthew G. Knepley }
29399d50c5ebSMatthew G. Knepley 
DMGlobalToLocalBegin_Swarm(DM dm,Vec g,InsertMode mode,Vec l)29409d50c5ebSMatthew G. Knepley PetscErrorCode DMGlobalToLocalBegin_Swarm(DM dm, Vec g, InsertMode mode, Vec l)
29419d50c5ebSMatthew G. Knepley {
29429d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
29439d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
29449d50c5ebSMatthew G. Knepley }
29459d50c5ebSMatthew G. Knepley 
DMGlobalToLocalEnd_Swarm(DM dm,Vec g,InsertMode mode,Vec l)29469d50c5ebSMatthew G. Knepley PetscErrorCode DMGlobalToLocalEnd_Swarm(DM dm, Vec g, InsertMode mode, Vec l)
29479d50c5ebSMatthew G. Knepley {
29489d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
29499d50c5ebSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd_Swarm(dm, g, mode, l));
29509d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
29519d50c5ebSMatthew G. Knepley }
2952