xref: /petsc/src/dm/impls/swarm/swarm.c (revision 9d50c5eb46ee8c42f8a07f60d3e08ee383dfb77a)
119307e5cSMatthew G. Knepley #include "petscdmswarm.h"
257795646SDave May #define PETSCDM_DLL
357795646SDave May #include <petsc/private/dmswarmimpl.h> /*I   "petscdmswarm.h"   I*/
4e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
50643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>
65917a6f0SStefano Zampini #include <petscviewer.h>
75917a6f0SStefano Zampini #include <petscdraw.h>
883c47955SMatthew G. Knepley #include <petscdmplex.h>
94cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h>
10279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
11d0c080abSJoseph Pusztay #include <petscdmlabel.h>
12d0c080abSJoseph Pusztay #include <petscsection.h>
1357795646SDave May 
14f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
15ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
16ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
17ed923d71SDave May 
18ea78f98cSLisandro Dalcin const char *DMSwarmTypeNames[]          = {"basic", "pic", NULL};
19ea78f98cSLisandro Dalcin const char *DMSwarmMigrateTypeNames[]   = {"basic", "dmcellnscatter", "dmcellexact", "user", NULL};
20ea78f98cSLisandro Dalcin const char *DMSwarmCollectTypeNames[]   = {"basic", "boundingbox", "general", "user", NULL};
21fca3fa51SMatthew G. Knepley const char *DMSwarmRemapTypeNames[]     = {"none", "pfak", "colella", "DMSwarmRemapType", "DMSWARM_REMAP_", NULL};
22ea78f98cSLisandro Dalcin const char *DMSwarmPICLayoutTypeNames[] = {"regular", "gauss", "subdivision", NULL};
23f0cdbbbaSDave May 
24f0cdbbbaSDave May const char DMSwarmField_pid[]     = "DMSwarm_pid";
25f0cdbbbaSDave May const char DMSwarmField_rank[]    = "DMSwarm_rank";
26f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
27f0cdbbbaSDave May 
282e956fe4SStefano Zampini PetscInt SwarmDataFieldId = -1;
292e956fe4SStefano Zampini 
3074d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
3174d0cae8SMatthew G. Knepley   #include <petscviewerhdf5.h>
3274d0cae8SMatthew G. Knepley 
3366976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer)
34d71ae5a4SJacob Faibussowitsch {
3574d0cae8SMatthew G. Knepley   DM        dm;
3674d0cae8SMatthew G. Knepley   PetscReal seqval;
3774d0cae8SMatthew G. Knepley   PetscInt  seqnum, bs;
38eb0c6899SMatthew G. Knepley   PetscBool isseq, ists;
3974d0cae8SMatthew G. Knepley 
4074d0cae8SMatthew G. Knepley   PetscFunctionBegin;
419566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
429566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(v, &bs));
439566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields"));
449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
459566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval));
46eb0c6899SMatthew G. Knepley   PetscCall(PetscViewerHDF5IsTimestepping(viewer, &ists));
47eb0c6899SMatthew G. Knepley   if (ists) PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum));
489566063dSJacob Faibussowitsch   /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */
499566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
509566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs));
519566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5374d0cae8SMatthew G. Knepley }
5474d0cae8SMatthew G. Knepley 
5566976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer)
56d71ae5a4SJacob Faibussowitsch {
5719307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
5874d0cae8SMatthew G. Knepley   Vec           coordinates;
5919307e5cSMatthew G. Knepley   PetscInt      Np, Nfc;
6074d0cae8SMatthew G. Knepley   PetscBool     isseq;
6119307e5cSMatthew G. Knepley   const char  **coordFields;
6274d0cae8SMatthew G. Knepley 
6374d0cae8SMatthew G. Knepley   PetscFunctionBegin;
6419307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
6519307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
6619307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
679566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetSize(dm, &Np));
6819307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateGlobalVectorFromField(dm, coordFields[0], &coordinates));
699566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
709566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles"));
719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq));
729566063dSJacob Faibussowitsch   PetscCall(VecViewNative(coordinates, viewer));
739566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np));
749566063dSJacob Faibussowitsch   PetscCall(PetscViewerHDF5PopGroup(viewer));
7519307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, coordFields[0], &coordinates));
763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7774d0cae8SMatthew G. Knepley }
7874d0cae8SMatthew G. Knepley #endif
7974d0cae8SMatthew G. Knepley 
8066976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer)
81d71ae5a4SJacob Faibussowitsch {
8274d0cae8SMatthew G. Knepley   DM dm;
83f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
8474d0cae8SMatthew G. Knepley   PetscBool ishdf5;
85f9558f5cSBarry Smith #endif
8674d0cae8SMatthew G. Knepley 
8774d0cae8SMatthew G. Knepley   PetscFunctionBegin;
889566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
8928b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
90f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
9274d0cae8SMatthew G. Knepley   if (ishdf5) {
939566063dSJacob Faibussowitsch     PetscCall(VecView_Swarm_HDF5_Internal(v, viewer));
943ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
9574d0cae8SMatthew G. Knepley   }
96f9558f5cSBarry Smith #endif
979566063dSJacob Faibussowitsch   PetscCall(VecViewNative(v, viewer));
983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9974d0cae8SMatthew G. Knepley }
10074d0cae8SMatthew G. Knepley 
101d52c2f21SMatthew G. Knepley /*@C
102d52c2f21SMatthew G. Knepley   DMSwarmVectorGetField - Gets the fields from which to define a `Vec` object
1030bf7c1c5SMatthew G. Knepley   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
1040bf7c1c5SMatthew G. Knepley 
1050bf7c1c5SMatthew G. Knepley   Not collective
1060bf7c1c5SMatthew G. Knepley 
1070bf7c1c5SMatthew G. Knepley   Input Parameter:
10819307e5cSMatthew G. Knepley . sw - a `DMSWARM`
1090bf7c1c5SMatthew G. Knepley 
110d52c2f21SMatthew G. Knepley   Output Parameters:
111d52c2f21SMatthew G. Knepley + Nf         - the number of fields
112d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field, or NULL if it has not been set
1130bf7c1c5SMatthew G. Knepley 
1140bf7c1c5SMatthew G. Knepley   Level: beginner
1150bf7c1c5SMatthew G. Knepley 
116d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
1170bf7c1c5SMatthew G. Knepley @*/
11819307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorGetField(DM sw, PetscInt *Nf, const char **fieldnames[])
1190bf7c1c5SMatthew G. Knepley {
12019307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
12119307e5cSMatthew G. Knepley 
1220bf7c1c5SMatthew G. Knepley   PetscFunctionBegin;
12319307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM);
12419307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
12519307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetFields(celldm, Nf, fieldnames));
1260bf7c1c5SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1270bf7c1c5SMatthew G. Knepley }
1280bf7c1c5SMatthew G. Knepley 
129cc4c1da9SBarry Smith /*@
13020f4b53cSBarry Smith   DMSwarmVectorDefineField - Sets the field from which to define a `Vec` object
13120f4b53cSBarry Smith   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
13257795646SDave May 
13320f4b53cSBarry Smith   Collective
13457795646SDave May 
13560225df5SJacob Faibussowitsch   Input Parameters:
13620f4b53cSBarry Smith + dm        - a `DMSWARM`
137d52c2f21SMatthew G. Knepley - fieldname - the textual name given to each registered field
13857795646SDave May 
139d3a51819SDave May   Level: beginner
14057795646SDave May 
141d3a51819SDave May   Notes:
14220f4b53cSBarry Smith   The field with name `fieldname` must be defined as having a data type of `PetscScalar`.
143e7af74c8SDave May 
14420f4b53cSBarry Smith   This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`.
14520f4b53cSBarry Smith   Multiple calls to `DMSwarmVectorDefineField()` are permitted.
146e7af74c8SDave May 
147d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineFields()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
148d3a51819SDave May @*/
149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[])
150d71ae5a4SJacob Faibussowitsch {
151d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
152d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmVectorDefineFields(dm, 1, &fieldname));
153d52c2f21SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
154d52c2f21SMatthew G. Knepley }
155d52c2f21SMatthew G. Knepley 
156d52c2f21SMatthew G. Knepley /*@C
157d52c2f21SMatthew G. Knepley   DMSwarmVectorDefineFields - Sets the fields from which to define a `Vec` object
158d52c2f21SMatthew G. Knepley   when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called
159d52c2f21SMatthew G. Knepley 
160d52c2f21SMatthew G. Knepley   Collective, No Fortran support
161d52c2f21SMatthew G. Knepley 
162d52c2f21SMatthew G. Knepley   Input Parameters:
16319307e5cSMatthew G. Knepley + sw         - a `DMSWARM`
164d52c2f21SMatthew G. Knepley . Nf         - the number of fields
165d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field
166d52c2f21SMatthew G. Knepley 
167d52c2f21SMatthew G. Knepley   Level: beginner
168d52c2f21SMatthew G. Knepley 
169d52c2f21SMatthew G. Knepley   Notes:
170d52c2f21SMatthew G. Knepley   Each field with name in `fieldnames` must be defined as having a data type of `PetscScalar`.
171d52c2f21SMatthew G. Knepley 
172d52c2f21SMatthew G. Knepley   This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`.
173d52c2f21SMatthew G. Knepley   Multiple calls to `DMSwarmVectorDefineField()` are permitted.
174d52c2f21SMatthew G. Knepley 
175d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()`
176d52c2f21SMatthew G. Knepley @*/
17719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineFields(DM sw, PetscInt Nf, const char *fieldnames[])
178d52c2f21SMatthew G. Knepley {
17919307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
18019307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
181b5bcf523SDave May 
182a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
18319307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM);
184d52c2f21SMatthew G. Knepley   if (fieldnames) PetscAssertPointer(fieldnames, 3);
18519307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
18619307e5cSMatthew G. Knepley   PetscCheck(Nf >= 0, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields must be non-negative, not %" PetscInt_FMT, Nf);
18719307e5cSMatthew G. Knepley   // Create a dummy cell DM if none has been specified (I think we should not support this mode)
18819307e5cSMatthew G. Knepley   if (!swarm->activeCellDM) {
18919307e5cSMatthew G. Knepley     DM            dm;
19019307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
191b5bcf523SDave May 
19219307e5cSMatthew G. Knepley     PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), &dm));
19319307e5cSMatthew G. Knepley     PetscCall(DMSetType(dm, DMSHELL));
19419307e5cSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, "dummy"));
19519307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 0, NULL, &celldm));
19619307e5cSMatthew G. Knepley     PetscCall(DMDestroy(&dm));
19719307e5cSMatthew G. Knepley     PetscCall(DMSwarmAddCellDM(sw, celldm));
19819307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMDestroy(&celldm));
19919307e5cSMatthew G. Knepley     PetscCall(DMSwarmSetCellDMActive(sw, "dummy"));
20019307e5cSMatthew G. Knepley   }
20119307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
20219307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) PetscCall(PetscFree(celldm->dmFields[f]));
20319307e5cSMatthew G. Knepley   PetscCall(PetscFree(celldm->dmFields));
20419307e5cSMatthew G. Knepley 
20519307e5cSMatthew G. Knepley   celldm->Nf = Nf;
20619307e5cSMatthew G. Knepley   PetscCall(PetscMalloc1(Nf, &celldm->dmFields));
207d52c2f21SMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
208d52c2f21SMatthew G. Knepley     PetscDataType type;
209d52c2f21SMatthew G. Knepley 
210d52c2f21SMatthew G. Knepley     // Check all fields are of type PETSC_REAL or PETSC_SCALAR
21119307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], NULL, &type));
21219307e5cSMatthew G. Knepley     PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
21319307e5cSMatthew G. Knepley     PetscCall(PetscStrallocpy(fieldnames[f], (char **)&celldm->dmFields[f]));
214d52c2f21SMatthew G. Knepley   }
2153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
216b5bcf523SDave May }
217b5bcf523SDave May 
218cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
21919307e5cSMatthew G. Knepley static PetscErrorCode DMCreateGlobalVector_Swarm(DM sw, Vec *vec)
220d71ae5a4SJacob Faibussowitsch {
22119307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
22219307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
223b5bcf523SDave May   Vec           x;
224b5bcf523SDave May   char          name[PETSC_MAX_PATH_LEN];
22519307e5cSMatthew G. Knepley   PetscInt      bs = 0, n;
226b5bcf523SDave May 
227a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
22819307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
22919307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
23019307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields");
23119307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
232cc651181SDave May 
233d52c2f21SMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
23419307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) {
23519307e5cSMatthew G. Knepley     PetscInt fbs;
236d52c2f21SMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
23719307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN));
23819307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL));
23919307e5cSMatthew G. Knepley     bs += fbs;
240d52c2f21SMatthew G. Knepley   }
24119307e5cSMatthew G. Knepley   PetscCall(VecCreate(PetscObjectComm((PetscObject)sw), &x));
2429566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
24319307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE));
24419307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(x, bs));
24519307e5cSMatthew G. Knepley   PetscCall(VecSetDM(x, sw));
2469566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
2479566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(x, VECOP_VIEW, (void (*)(void))VecView_Swarm));
248b5bcf523SDave May   *vec = x;
2493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250b5bcf523SDave May }
251b5bcf523SDave May 
252b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
25319307e5cSMatthew G. Knepley static PetscErrorCode DMCreateLocalVector_Swarm(DM sw, Vec *vec)
254d71ae5a4SJacob Faibussowitsch {
25519307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
25619307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
257b5bcf523SDave May   Vec           x;
258b5bcf523SDave May   char          name[PETSC_MAX_PATH_LEN];
25919307e5cSMatthew G. Knepley   PetscInt      bs = 0, n;
260b5bcf523SDave May 
261a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
26219307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
26319307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
26419307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields");
26519307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
266cc651181SDave May 
267d52c2f21SMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
26819307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nf; ++f) {
26919307e5cSMatthew G. Knepley     PetscInt fbs;
270d52c2f21SMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
27119307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN));
27219307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL));
27319307e5cSMatthew G. Knepley     bs += fbs;
274d52c2f21SMatthew G. Knepley   }
2759566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &x));
2769566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)x, name));
27719307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE));
27819307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(x, bs));
27919307e5cSMatthew G. Knepley   PetscCall(VecSetDM(x, sw));
2809566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(x));
281b5bcf523SDave May   *vec = x;
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283b5bcf523SDave May }
284b5bcf523SDave May 
285d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
286d71ae5a4SJacob Faibussowitsch {
287fb1bcc12SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
28877048351SPatrick Sanan   DMSwarmDataField gfield;
2892e956fe4SStefano Zampini   PetscInt         bs, nlocal, fid = -1, cfid = -2;
2902e956fe4SStefano Zampini   PetscBool        flg;
291d3a51819SDave May 
292fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
2932e956fe4SStefano Zampini   /* check vector is an inplace array */
2942e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
2952e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg));
296ea17275aSJose E. Roman   (void)flg; /* avoid compiler warning */
297e978a55eSPierre 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);
2989566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(*vec, &nlocal));
2999566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(*vec, &bs));
30008401ef6SPierre 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");
3019566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
3029566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
3038df78e51SMark Adams   PetscCall(VecResetArray(*vec));
3049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(vec));
3053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
306fb1bcc12SMatthew G. Knepley }
307fb1bcc12SMatthew G. Knepley 
308d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
309d71ae5a4SJacob Faibussowitsch {
310fb1bcc12SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)dm->data;
311fb1bcc12SMatthew G. Knepley   PetscDataType type;
312fb1bcc12SMatthew G. Knepley   PetscScalar  *array;
3132e956fe4SStefano Zampini   PetscInt      bs, n, fid;
314fb1bcc12SMatthew G. Knepley   char          name[PETSC_MAX_PATH_LEN];
315e4fbd051SBarry Smith   PetscMPIInt   size;
3167f92dde0SRylanor   PetscBool     iscuda, iskokkos, iship;
317fb1bcc12SMatthew G. Knepley 
318fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
3199566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
3209566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
3219566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array));
32208401ef6SPierre Jolivet   PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
323fb1bcc12SMatthew G. Knepley 
3249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
3258df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos));
3268df78e51SMark Adams   PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda));
3277f92dde0SRylanor   PetscCall(PetscStrcmp(dm->vectype, VECHIP, &iship));
3288df78e51SMark Adams   PetscCall(VecCreate(comm, vec));
3298df78e51SMark Adams   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
3308df78e51SMark Adams   PetscCall(VecSetBlockSize(*vec, bs));
3318df78e51SMark Adams   if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS));
3328df78e51SMark Adams   else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA));
3337f92dde0SRylanor   else if (iship) PetscCall(VecSetType(*vec, VECHIP));
3348df78e51SMark Adams   else PetscCall(VecSetType(*vec, VECSTANDARD));
3358df78e51SMark Adams   PetscCall(VecPlaceArray(*vec, array));
3368df78e51SMark Adams 
3379566063dSJacob Faibussowitsch   PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname));
3389566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
339fb1bcc12SMatthew G. Knepley 
340fb1bcc12SMatthew G. Knepley   /* Set guard */
3412e956fe4SStefano Zampini   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid));
3422e956fe4SStefano Zampini   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid));
34374d0cae8SMatthew G. Knepley 
3449566063dSJacob Faibussowitsch   PetscCall(VecSetDM(*vec, dm));
3459566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm));
3463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
347fb1bcc12SMatthew G. Knepley }
348fb1bcc12SMatthew G. Knepley 
34919307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], Vec *vec)
35019307e5cSMatthew G. Knepley {
35119307e5cSMatthew G. Knepley   DM_Swarm          *swarm = (DM_Swarm *)sw->data;
35219307e5cSMatthew G. Knepley   const PetscScalar *array;
35319307e5cSMatthew G. Knepley   PetscInt           bs, n, id = 0, cid = -2;
35419307e5cSMatthew G. Knepley   PetscBool          flg;
35519307e5cSMatthew G. Knepley 
35619307e5cSMatthew G. Knepley   PetscFunctionBegin;
35719307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
35819307e5cSMatthew G. Knepley     PetscInt fid;
35919307e5cSMatthew G. Knepley 
36019307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid));
36119307e5cSMatthew G. Knepley     id += fid;
36219307e5cSMatthew G. Knepley   }
36319307e5cSMatthew G. Knepley   PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cid, flg));
36419307e5cSMatthew G. Knepley   (void)flg; /* avoid compiler warning */
36519307e5cSMatthew 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);
36619307e5cSMatthew G. Knepley   PetscCall(VecGetLocalSize(*vec, &n));
36719307e5cSMatthew G. Knepley   PetscCall(VecGetBlockSize(*vec, &bs));
36819307e5cSMatthew G. Knepley   n /= bs;
36919307e5cSMatthew 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");
37019307e5cSMatthew G. Knepley   PetscCall(VecGetArrayRead(*vec, &array));
37119307e5cSMatthew G. Knepley   for (PetscInt f = 0, off = 0; f < Nf; ++f) {
37219307e5cSMatthew G. Knepley     PetscScalar  *farray;
37319307e5cSMatthew G. Knepley     PetscDataType ftype;
37419307e5cSMatthew G. Knepley     PetscInt      fbs;
37519307e5cSMatthew G. Knepley 
37619307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
37719307e5cSMatthew G. Knepley     PetscCheck(off + fbs <= bs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid blocksize %" PetscInt_FMT " < %" PetscInt_FMT, bs, off + fbs);
37819307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i) {
37919307e5cSMatthew G. Knepley       for (PetscInt b = 0; b < fbs; ++b) farray[i * fbs + b] = array[i * bs + off + b];
38019307e5cSMatthew G. Knepley     }
38119307e5cSMatthew G. Knepley     off += fbs;
38219307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
38319307e5cSMatthew G. Knepley   }
38419307e5cSMatthew G. Knepley   PetscCall(VecRestoreArrayRead(*vec, &array));
38519307e5cSMatthew G. Knepley   PetscCall(VecDestroy(vec));
38619307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
38719307e5cSMatthew G. Knepley }
38819307e5cSMatthew G. Knepley 
38919307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], MPI_Comm comm, Vec *vec)
39019307e5cSMatthew G. Knepley {
39119307e5cSMatthew G. Knepley   DM_Swarm    *swarm = (DM_Swarm *)sw->data;
39219307e5cSMatthew G. Knepley   PetscScalar *array;
39319307e5cSMatthew G. Knepley   PetscInt     n, bs = 0, id = 0;
39419307e5cSMatthew G. Knepley   char         name[PETSC_MAX_PATH_LEN];
39519307e5cSMatthew G. Knepley 
39619307e5cSMatthew G. Knepley   PetscFunctionBegin;
39719307e5cSMatthew G. Knepley   if (!swarm->issetup) PetscCall(DMSetUp(sw));
39819307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL));
39919307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
40019307e5cSMatthew G. Knepley     PetscDataType ftype;
40119307e5cSMatthew G. Knepley     PetscInt      fbs;
40219307e5cSMatthew G. Knepley 
40319307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], &fbs, &ftype));
40419307e5cSMatthew G. Knepley     PetscCheck(ftype == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
40519307e5cSMatthew G. Knepley     bs += fbs;
40619307e5cSMatthew G. Knepley   }
40719307e5cSMatthew G. Knepley 
40819307e5cSMatthew G. Knepley   PetscCall(VecCreate(comm, vec));
40919307e5cSMatthew G. Knepley   PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE));
41019307e5cSMatthew G. Knepley   PetscCall(VecSetBlockSize(*vec, bs));
41119307e5cSMatthew G. Knepley   PetscCall(VecSetType(*vec, sw->vectype));
41219307e5cSMatthew G. Knepley 
41319307e5cSMatthew G. Knepley   PetscCall(VecGetArrayWrite(*vec, &array));
41419307e5cSMatthew G. Knepley   for (PetscInt f = 0, off = 0; f < Nf; ++f) {
41519307e5cSMatthew G. Knepley     PetscScalar  *farray;
41619307e5cSMatthew G. Knepley     PetscDataType ftype;
41719307e5cSMatthew G. Knepley     PetscInt      fbs;
41819307e5cSMatthew G. Knepley 
41919307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
42019307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i) {
42119307e5cSMatthew G. Knepley       for (PetscInt b = 0; b < fbs; ++b) array[i * bs + off + b] = farray[i * fbs + b];
42219307e5cSMatthew G. Knepley     }
42319307e5cSMatthew G. Knepley     off += fbs;
42419307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray));
42519307e5cSMatthew G. Knepley   }
42619307e5cSMatthew G. Knepley   PetscCall(VecRestoreArrayWrite(*vec, &array));
42719307e5cSMatthew G. Knepley 
42819307e5cSMatthew G. Knepley   PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN));
42919307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
43019307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN));
43119307e5cSMatthew G. Knepley     PetscCall(PetscStrlcat(name, fieldnames[f], PETSC_MAX_PATH_LEN));
43219307e5cSMatthew G. Knepley   }
43319307e5cSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*vec, name));
43419307e5cSMatthew G. Knepley 
43519307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
43619307e5cSMatthew G. Knepley     PetscInt fid;
43719307e5cSMatthew G. Knepley 
43819307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid));
43919307e5cSMatthew G. Knepley     id += fid;
44019307e5cSMatthew G. Knepley   }
44119307e5cSMatthew G. Knepley   PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, id));
44219307e5cSMatthew G. Knepley 
44319307e5cSMatthew G. Knepley   PetscCall(VecSetDM(*vec, sw));
44419307e5cSMatthew G. Knepley   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm));
44519307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
44619307e5cSMatthew G. Knepley }
44719307e5cSMatthew G. Knepley 
4480643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
4490643ed39SMatthew G. Knepley 
4500643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
4510643ed39SMatthew G. Knepley 
4520643ed39SMatthew G. Knepley    and a particle function is given by
4530643ed39SMatthew G. Knepley 
4540643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
4550643ed39SMatthew G. Knepley 
4560643ed39SMatthew G. Knepley    then we want to require that
4570643ed39SMatthew G. Knepley 
4580643ed39SMatthew G. Knepley      M \hat f = M_p f
4590643ed39SMatthew G. Knepley 
4600643ed39SMatthew G. Knepley    where the particle mass matrix is given by
4610643ed39SMatthew G. Knepley 
4620643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
4630643ed39SMatthew G. Knepley 
4640643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
4650643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
4660643ed39SMatthew G. Knepley */
467d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
468d71ae5a4SJacob Faibussowitsch {
46983c47955SMatthew G. Knepley   const char   *name = "Mass Matrix";
4700643ed39SMatthew G. Knepley   MPI_Comm      comm;
47119307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
47283c47955SMatthew G. Knepley   PetscDS       prob;
47383c47955SMatthew G. Knepley   PetscSection  fsection, globalFSection;
474e8f14785SLisandro Dalcin   PetscHSetIJ   ht;
4750643ed39SMatthew G. Knepley   PetscLayout   rLayout, colLayout;
47683c47955SMatthew G. Knepley   PetscInt     *dnz, *onz;
477adb2528bSMark Adams   PetscInt      locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4780643ed39SMatthew G. Knepley   PetscReal    *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
47983c47955SMatthew G. Knepley   PetscScalar  *elemMat;
48019307e5cSMatthew G. Knepley   PetscInt      dim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0, totNc = 0;
48119307e5cSMatthew G. Knepley   const char  **coordFields;
48219307e5cSMatthew G. Knepley   PetscReal   **coordVals;
48319307e5cSMatthew G. Knepley   PetscInt     *bs;
48483c47955SMatthew G. Knepley 
48583c47955SMatthew G. Knepley   PetscFunctionBegin;
4869566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
4879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &dim));
4889566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
4899566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
4909566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
4919566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ));
4929566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
4939566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
4949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
4959566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
49683c47955SMatthew G. Knepley 
49719307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmc, &celldm));
49819307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
49919307e5cSMatthew G. Knepley   PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs));
500d52c2f21SMatthew G. Knepley 
5019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
5029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
5039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
5049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
5059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
5069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
5070643ed39SMatthew G. Knepley 
5089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
5099566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
5109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
5119566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
5129566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
5139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
5140643ed39SMatthew G. Knepley 
5159566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
5169566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
51753e60ab4SJoseph Pusztay 
5189566063dSJacob Faibussowitsch   PetscCall(PetscSynchronizedFlush(comm, NULL));
51919307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
5200bf7c1c5SMatthew G. Knepley     PetscObject  obj;
5210bf7c1c5SMatthew G. Knepley     PetscClassId id;
5220bf7c1c5SMatthew G. Knepley     PetscInt     Nc;
5230bf7c1c5SMatthew G. Knepley 
5240bf7c1c5SMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5250bf7c1c5SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
5260bf7c1c5SMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
5270bf7c1c5SMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
5280bf7c1c5SMatthew G. Knepley     totNc += Nc;
5290bf7c1c5SMatthew G. Knepley   }
5300643ed39SMatthew G. Knepley   /* count non-zeros */
5319566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
53219307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
5330bf7c1c5SMatthew G. Knepley     PetscObject  obj;
5340bf7c1c5SMatthew G. Knepley     PetscClassId id;
5350bf7c1c5SMatthew G. Knepley     PetscInt     Nc;
5360bf7c1c5SMatthew G. Knepley 
5370bf7c1c5SMatthew G. Knepley     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
5380bf7c1c5SMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
5390bf7c1c5SMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
5400bf7c1c5SMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
5410bf7c1c5SMatthew G. Knepley 
54219307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
5430643ed39SMatthew G. Knepley       PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */
54483c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
54583c47955SMatthew G. Knepley 
5469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5479566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
548fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
54983c47955SMatthew G. Knepley       {
550e8f14785SLisandro Dalcin         PetscHashIJKey key;
551e8f14785SLisandro Dalcin         PetscBool      missing;
5520bf7c1c5SMatthew G. Knepley         for (PetscInt i = 0; i < numFIndices; ++i) {
553adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
554adb2528bSMark Adams           if (key.j >= 0) {
55583c47955SMatthew G. Knepley             /* Get indices for coarse elements */
5560bf7c1c5SMatthew G. Knepley             for (PetscInt j = 0; j < numCIndices; ++j) {
5570bf7c1c5SMatthew G. Knepley               for (PetscInt c = 0; c < Nc; ++c) {
5580bf7c1c5SMatthew G. Knepley                 // TODO Need field offset on particle here
5590bf7c1c5SMatthew G. Knepley                 key.i = cindices[j] * totNc + c + rStart; /* global cols (from Swarm) */
560adb2528bSMark Adams                 if (key.i < 0) continue;
5619566063dSJacob Faibussowitsch                 PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
56283c47955SMatthew G. Knepley                 if (missing) {
5630643ed39SMatthew G. Knepley                   if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
564e8f14785SLisandro Dalcin                   else ++onz[key.i - rStart];
56563a3b9bcSJacob Faibussowitsch                 } else SETERRQ(PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j);
56683c47955SMatthew G. Knepley               }
567fc7c92abSMatthew G. Knepley             }
568fc7c92abSMatthew G. Knepley           }
5690bf7c1c5SMatthew G. Knepley         }
570fe11354eSMatthew G. Knepley         PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
57183c47955SMatthew G. Knepley       }
5729566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
57383c47955SMatthew G. Knepley     }
57483c47955SMatthew G. Knepley   }
5759566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
5769566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
5779566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
5789566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
5790bf7c1c5SMatthew G. Knepley   PetscCall(PetscMalloc3(maxC * totNc * totDim, &elemMat, maxC * totNc, &rowIDXs, maxC * dim, &xi));
58019307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
581ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
58283c47955SMatthew G. Knepley     PetscObject     obj;
583ad9634fcSMatthew G. Knepley     PetscClassId    id;
58419307e5cSMatthew G. Knepley     PetscInt        Nc;
58583c47955SMatthew G. Knepley 
5869566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
587ad9634fcSMatthew G. Knepley     PetscCall(PetscObjectGetClassId(obj, &id));
588ad9634fcSMatthew G. Knepley     if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
589ad9634fcSMatthew G. Knepley     else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
590ea7032a0SMatthew G. Knepley 
59119307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
59219307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
59383c47955SMatthew G. Knepley       PetscInt *findices, *cindices;
59483c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
59583c47955SMatthew G. Knepley 
5960643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5979566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
5989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
5999566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
60019307e5cSMatthew G. Knepley       for (PetscInt j = 0; j < numCIndices; ++j) {
60119307e5cSMatthew G. Knepley         PetscReal xr[8];
60219307e5cSMatthew G. Knepley         PetscInt  off = 0;
60319307e5cSMatthew G. Knepley 
60419307e5cSMatthew G. Knepley         for (PetscInt i = 0; i < Nfc; ++i) {
60519307e5cSMatthew G. Knepley           for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[j] * bs[i] + b];
60619307e5cSMatthew G. Knepley         }
60719307e5cSMatthew 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);
60819307e5cSMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, xr, &xi[j * dim]);
60919307e5cSMatthew G. Knepley       }
610ad9634fcSMatthew G. Knepley       if (id == PETSCFE_CLASSID) PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
611ad9634fcSMatthew G. Knepley       else PetscCall(PetscFVCreateTabulation((PetscFV)obj, 1, numCIndices, xi, 0, &Tcoarse));
61283c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
6130bf7c1c5SMatthew G. Knepley       PetscCall(PetscArrayzero(elemMat, numCIndices * Nc * totDim));
6140bf7c1c5SMatthew G. Knepley       for (PetscInt i = 0; i < numFIndices / Nc; ++i) {
6150bf7c1c5SMatthew G. Knepley         for (PetscInt j = 0; j < numCIndices; ++j) {
6160bf7c1c5SMatthew G. Knepley           for (PetscInt c = 0; c < Nc; ++c) {
6170bf7c1c5SMatthew G. Knepley             // TODO Need field offset on particle and field here
6180643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
6190bf7c1c5SMatthew G. Knepley             elemMat[(j * totNc + c) * numFIndices + i * Nc + c] += Tcoarse->T[0][(j * numFIndices + i * Nc + c) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
62083c47955SMatthew G. Knepley           }
6210643ed39SMatthew G. Knepley         }
6220643ed39SMatthew G. Knepley       }
6230bf7c1c5SMatthew G. Knepley       for (PetscInt j = 0; j < numCIndices; ++j)
6240bf7c1c5SMatthew G. Knepley         // TODO Need field offset on particle here
6250bf7c1c5SMatthew G. Knepley         for (PetscInt c = 0; c < Nc; ++c) rowIDXs[j * Nc + c] = cindices[j] * totNc + c + rStart;
6260bf7c1c5SMatthew G. Knepley       if (0) PetscCall(DMPrintCellMatrix(cell, name, numCIndices * Nc, numFIndices, elemMat));
6270bf7c1c5SMatthew G. Knepley       PetscCall(MatSetValues(mass, numCIndices * Nc, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES));
628fe11354eSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
6299566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
6309566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
63183c47955SMatthew G. Knepley     }
63219307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
63383c47955SMatthew G. Knepley   }
6349566063dSJacob Faibussowitsch   PetscCall(PetscFree3(elemMat, rowIDXs, xi));
6359566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
6369566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
63719307e5cSMatthew G. Knepley   PetscCall(PetscFree2(coordVals, bs));
6389566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
6399566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
6403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64183c47955SMatthew G. Knepley }
64283c47955SMatthew G. Knepley 
643d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */
644d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m)
645d71ae5a4SJacob Faibussowitsch {
646d0c080abSJoseph Pusztay   Vec      field;
647d0c080abSJoseph Pusztay   PetscInt size;
648d0c080abSJoseph Pusztay 
649d0c080abSJoseph Pusztay   PetscFunctionBegin;
6509566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(sw, &field));
6519566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(field, &size));
6529566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(sw, &field));
6539566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, m));
6549566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*m));
6559566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size));
6569566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL));
6579566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(*m));
6589566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY));
6599566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY));
6609566063dSJacob Faibussowitsch   PetscCall(MatShift(*m, 1.0));
6619566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*m, sw));
6623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
663d0c080abSJoseph Pusztay }
664d0c080abSJoseph Pusztay 
665adb2528bSMark Adams /* FEM cols, Particle rows */
666d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
667d71ae5a4SJacob Faibussowitsch {
66819307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
669895a1698SMatthew G. Knepley   PetscSection  gsf;
67019307e5cSMatthew G. Knepley   PetscInt      m, n, Np, bs;
67183c47955SMatthew G. Knepley   void         *ctx;
67283c47955SMatthew G. Knepley 
67383c47955SMatthew G. Knepley   PetscFunctionBegin;
67419307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmCoarse, &celldm));
67519307e5cSMatthew G. Knepley   PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)dmCoarse), PETSC_ERR_USER, "Active cell DM does not define any fields");
6769566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
6779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
6780bf7c1c5SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dmCoarse, &Np));
67919307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetBlockSize(celldm, dmCoarse, &bs));
68019307e5cSMatthew G. Knepley   n = Np * bs;
6819566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
6829566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE));
6839566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
6849566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
68583c47955SMatthew G. Knepley 
6869566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
6879566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
6883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68983c47955SMatthew G. Knepley }
69083c47955SMatthew G. Knepley 
691d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
692d71ae5a4SJacob Faibussowitsch {
6934cc7f7b2SMatthew G. Knepley   const char   *name = "Mass Matrix Square";
6944cc7f7b2SMatthew G. Knepley   MPI_Comm      comm;
69519307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
6964cc7f7b2SMatthew G. Knepley   PetscDS       prob;
6974cc7f7b2SMatthew G. Knepley   PetscSection  fsection, globalFSection;
6984cc7f7b2SMatthew G. Knepley   PetscHSetIJ   ht;
6994cc7f7b2SMatthew G. Knepley   PetscLayout   rLayout, colLayout;
7004cc7f7b2SMatthew G. Knepley   PetscInt     *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
7014cc7f7b2SMatthew G. Knepley   PetscInt      locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
7024cc7f7b2SMatthew G. Knepley   PetscReal    *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
7034cc7f7b2SMatthew G. Knepley   PetscScalar  *elemMat, *elemMatSq;
70419307e5cSMatthew G. Knepley   PetscInt      cdim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0;
70519307e5cSMatthew G. Knepley   const char  **coordFields;
70619307e5cSMatthew G. Knepley   PetscReal   **coordVals;
70719307e5cSMatthew G. Knepley   PetscInt     *bs;
7084cc7f7b2SMatthew G. Knepley 
7094cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
7109566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)mass, &comm));
7119566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmf, &cdim));
7129566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmf, &prob));
7139566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(prob, &Nf));
7149566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalDimension(prob, &totDim));
7159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ));
7169566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dmf, &fsection));
7179566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd));
7199566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mass, &locRows, &locCols));
7204cc7f7b2SMatthew G. Knepley 
72119307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dmc, &celldm));
72219307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
72319307e5cSMatthew G. Knepley   PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs));
724d52c2f21SMatthew G. Knepley 
7259566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &colLayout));
7269566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(colLayout, locCols));
7279566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(colLayout, 1));
7289566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(colLayout));
7299566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd));
7309566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&colLayout));
7314cc7f7b2SMatthew G. Knepley 
7329566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(comm, &rLayout));
7339566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(rLayout, locRows));
7349566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(rLayout, 1));
7359566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(rLayout));
7369566063dSJacob Faibussowitsch   PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL));
7379566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&rLayout));
7384cc7f7b2SMatthew G. Knepley 
7399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmf, &depth));
7409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize));
7414cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth);
7429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(maxAdjSize, &adj));
7434cc7f7b2SMatthew G. Knepley 
7449566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz));
7459566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJCreate(&ht));
7464cc7f7b2SMatthew G. Knepley   /* Count nonzeros
7474cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
7484cc7f7b2SMatthew G. Knepley   */
7499566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(dmc));
75019307e5cSMatthew G. Knepley   for (PetscInt cell = cStart; cell < cEnd; ++cell) {
7514cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
7524cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
7534cc7f7b2SMatthew G. Knepley #if 0
7544cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
7554cc7f7b2SMatthew G. Knepley #endif
7564cc7f7b2SMatthew G. Knepley 
7579566063dSJacob Faibussowitsch     PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
7584cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
7594cc7f7b2SMatthew G. Knepley     /* Diagonal block */
76019307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices;
7614cc7f7b2SMatthew G. Knepley #if 0
7624cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
7639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj));
7644cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
7654cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
7664cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
7674cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
7684cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
7694cc7f7b2SMatthew G. Knepley 
7709566063dSJacob Faibussowitsch         PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
7714cc7f7b2SMatthew G. Knepley         {
7724cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
7734cc7f7b2SMatthew G. Knepley           PetscBool      missing;
7744cc7f7b2SMatthew G. Knepley 
7754cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
7764cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
7774cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
7784cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
7794cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
7804cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
7819566063dSJacob Faibussowitsch               PetscCall(PetscHSetIJQueryAdd(ht, key, &missing));
7824cc7f7b2SMatthew G. Knepley               if (missing) {
7834cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
7844cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
7854cc7f7b2SMatthew G. Knepley               }
7864cc7f7b2SMatthew G. Knepley             }
7874cc7f7b2SMatthew G. Knepley           }
7884cc7f7b2SMatthew G. Knepley         }
789fe11354eSMatthew G. Knepley         PetscCall(DMSwarmSortRestorePointsPerCell(dmc, ncell, &numNCIndices, &ncindices));
7904cc7f7b2SMatthew G. Knepley       }
7914cc7f7b2SMatthew G. Knepley     }
7924cc7f7b2SMatthew G. Knepley #endif
793fe11354eSMatthew G. Knepley     PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
7944cc7f7b2SMatthew G. Knepley   }
7959566063dSJacob Faibussowitsch   PetscCall(PetscHSetIJDestroy(&ht));
7969566063dSJacob Faibussowitsch   PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL));
7979566063dSJacob Faibussowitsch   PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
7989566063dSJacob Faibussowitsch   PetscCall(PetscFree2(dnz, onz));
7999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi));
8004cc7f7b2SMatthew G. Knepley   /* Fill in values
8014cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
8024cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
8034cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
8044cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
8054cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
8064cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
8074cc7f7b2SMatthew G. Knepley          Insert block
8084cc7f7b2SMatthew G. Knepley   */
80919307e5cSMatthew G. Knepley   for (PetscInt field = 0; field < Nf; ++field) {
8104cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
8114cc7f7b2SMatthew G. Knepley     PetscObject     obj;
81219307e5cSMatthew G. Knepley     PetscInt        Nc;
8134cc7f7b2SMatthew G. Knepley 
8149566063dSJacob Faibussowitsch     PetscCall(PetscDSGetDiscretization(prob, field, &obj));
8159566063dSJacob Faibussowitsch     PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
81663a3b9bcSJacob Faibussowitsch     PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc);
81719307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
81819307e5cSMatthew G. Knepley     for (PetscInt cell = cStart; cell < cEnd; ++cell) {
8194cc7f7b2SMatthew G. Knepley       PetscInt *findices, *cindices;
8204cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
8214cc7f7b2SMatthew G. Knepley 
8224cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
8239566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ));
8249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
8259566063dSJacob Faibussowitsch       PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices));
82619307e5cSMatthew G. Knepley       for (PetscInt p = 0; p < numCIndices; ++p) {
82719307e5cSMatthew G. Knepley         PetscReal xr[8];
82819307e5cSMatthew G. Knepley         PetscInt  off = 0;
82919307e5cSMatthew G. Knepley 
83019307e5cSMatthew G. Knepley         for (PetscInt i = 0; i < Nfc; ++i) {
83119307e5cSMatthew G. Knepley           for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[p] * bs[i] + b];
83219307e5cSMatthew G. Knepley         }
83319307e5cSMatthew 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);
83419307e5cSMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, xr, &xi[p * cdim]);
83519307e5cSMatthew G. Knepley       }
8369566063dSJacob Faibussowitsch       PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse));
8374cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
8389566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elemMat, numCIndices * totDim));
83919307e5cSMatthew G. Knepley       for (PetscInt i = 0; i < numFIndices; ++i) {
84019307e5cSMatthew G. Knepley         for (PetscInt p = 0; p < numCIndices; ++p) {
84119307e5cSMatthew G. Knepley           for (PetscInt c = 0; c < Nc; ++c) {
8424cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
8434cc7f7b2SMatthew G. Knepley             elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ);
8444cc7f7b2SMatthew G. Knepley           }
8454cc7f7b2SMatthew G. Knepley         }
8464cc7f7b2SMatthew G. Knepley       }
8479566063dSJacob Faibussowitsch       PetscCall(PetscTabulationDestroy(&Tcoarse));
84819307e5cSMatthew G. Knepley       for (PetscInt p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
8499566063dSJacob Faibussowitsch       if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat));
8504cc7f7b2SMatthew G. Knepley       /* Block diagonal */
85178884ca7SMatthew G. Knepley       if (numCIndices) {
8524cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
8534cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
8544cc7f7b2SMatthew G. Knepley 
8559566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numCIndices, &blasn));
8569566063dSJacob Faibussowitsch         PetscCall(PetscBLASIntCast(numFIndices, &blask));
857792fecdfSBarry Smith         PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn));
8584cc7f7b2SMatthew G. Knepley       }
8599566063dSJacob Faibussowitsch       PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES));
8604cf0e950SBarry Smith       /* TODO off-diagonal */
861fe11354eSMatthew G. Knepley       PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices));
8629566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL));
8634cc7f7b2SMatthew G. Knepley     }
86419307e5cSMatthew G. Knepley     for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i]));
8654cc7f7b2SMatthew G. Knepley   }
8669566063dSJacob Faibussowitsch   PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi));
8679566063dSJacob Faibussowitsch   PetscCall(PetscFree(adj));
8689566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(dmc));
8699566063dSJacob Faibussowitsch   PetscCall(PetscFree3(v0, J, invJ));
87019307e5cSMatthew G. Knepley   PetscCall(PetscFree2(coordVals, bs));
8719566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY));
8729566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY));
8733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8744cc7f7b2SMatthew G. Knepley }
8754cc7f7b2SMatthew G. Knepley 
876cc4c1da9SBarry Smith /*@
8774cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
8784cc7f7b2SMatthew G. Knepley 
87920f4b53cSBarry Smith   Collective
8804cc7f7b2SMatthew G. Knepley 
88160225df5SJacob Faibussowitsch   Input Parameters:
88220f4b53cSBarry Smith + dmCoarse - a `DMSWARM`
88320f4b53cSBarry Smith - dmFine   - a `DMPLEX`
8844cc7f7b2SMatthew G. Knepley 
88560225df5SJacob Faibussowitsch   Output Parameter:
8864cc7f7b2SMatthew G. Knepley . mass - the square of the particle mass matrix
8874cc7f7b2SMatthew G. Knepley 
8884cc7f7b2SMatthew G. Knepley   Level: advanced
8894cc7f7b2SMatthew G. Knepley 
89020f4b53cSBarry Smith   Note:
8914cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
8924cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
8934cc7f7b2SMatthew G. Knepley 
89420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMCreateMassMatrix()`
8954cc7f7b2SMatthew G. Knepley @*/
896d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
897d71ae5a4SJacob Faibussowitsch {
8984cc7f7b2SMatthew G. Knepley   PetscInt n;
8994cc7f7b2SMatthew G. Knepley   void    *ctx;
9004cc7f7b2SMatthew G. Knepley 
9014cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
9029566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dmCoarse, &n));
9039566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
9049566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE));
9059566063dSJacob Faibussowitsch   PetscCall(MatSetType(*mass, dmCoarse->mattype));
9069566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
9074cc7f7b2SMatthew G. Knepley 
9089566063dSJacob Faibussowitsch   PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx));
9099566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view"));
9103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9114cc7f7b2SMatthew G. Knepley }
9124cc7f7b2SMatthew G. Knepley 
913cc4c1da9SBarry Smith /*@
91420f4b53cSBarry Smith   DMSwarmCreateGlobalVectorFromField - Creates a `Vec` object sharing the array associated with a given field
915d3a51819SDave May 
91620f4b53cSBarry Smith   Collective
917d3a51819SDave May 
91860225df5SJacob Faibussowitsch   Input Parameters:
91920f4b53cSBarry Smith + dm        - a `DMSWARM`
92062741f57SDave May - fieldname - the textual name given to a registered field
921d3a51819SDave May 
92260225df5SJacob Faibussowitsch   Output Parameter:
923d3a51819SDave May . vec - the vector
924d3a51819SDave May 
925d3a51819SDave May   Level: beginner
926d3a51819SDave May 
927cc4c1da9SBarry Smith   Note:
92820f4b53cSBarry Smith   The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromField()`.
9298b8a3813SDave May 
93020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()`
931d3a51819SDave May @*/
932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
933d71ae5a4SJacob Faibussowitsch {
934fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
935b5bcf523SDave May 
936fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
937ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
9389566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
9393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
940b5bcf523SDave May }
941b5bcf523SDave May 
942cc4c1da9SBarry Smith /*@
94320f4b53cSBarry Smith   DMSwarmDestroyGlobalVectorFromField - Destroys the `Vec` object which share the array associated with a given field
944d3a51819SDave May 
94520f4b53cSBarry Smith   Collective
946d3a51819SDave May 
94760225df5SJacob Faibussowitsch   Input Parameters:
94820f4b53cSBarry Smith + dm        - a `DMSWARM`
94962741f57SDave May - fieldname - the textual name given to a registered field
950d3a51819SDave May 
95160225df5SJacob Faibussowitsch   Output Parameter:
952d3a51819SDave May . vec - the vector
953d3a51819SDave May 
954d3a51819SDave May   Level: beginner
955d3a51819SDave May 
95620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
957d3a51819SDave May @*/
958d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec)
959d71ae5a4SJacob Faibussowitsch {
960fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
961ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
9629566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
9633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
964b5bcf523SDave May }
965b5bcf523SDave May 
966cc4c1da9SBarry Smith /*@
96720f4b53cSBarry Smith   DMSwarmCreateLocalVectorFromField - Creates a `Vec` object sharing the array associated with a given field
968fb1bcc12SMatthew G. Knepley 
96920f4b53cSBarry Smith   Collective
970fb1bcc12SMatthew G. Knepley 
97160225df5SJacob Faibussowitsch   Input Parameters:
97220f4b53cSBarry Smith + dm        - a `DMSWARM`
97362741f57SDave May - fieldname - the textual name given to a registered field
974fb1bcc12SMatthew G. Knepley 
97560225df5SJacob Faibussowitsch   Output Parameter:
976fb1bcc12SMatthew G. Knepley . vec - the vector
977fb1bcc12SMatthew G. Knepley 
978fb1bcc12SMatthew G. Knepley   Level: beginner
979fb1bcc12SMatthew G. Knepley 
98020f4b53cSBarry Smith   Note:
9818b8a3813SDave May   The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
9828b8a3813SDave May 
98320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
984fb1bcc12SMatthew G. Knepley @*/
985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
986d71ae5a4SJacob Faibussowitsch {
987fb1bcc12SMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
988bbe8250bSMatthew G. Knepley 
989fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
9909566063dSJacob Faibussowitsch   PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec));
9913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
992bbe8250bSMatthew G. Knepley }
993fb1bcc12SMatthew G. Knepley 
994cc4c1da9SBarry Smith /*@
99520f4b53cSBarry Smith   DMSwarmDestroyLocalVectorFromField - Destroys the `Vec` object which share the array associated with a given field
996fb1bcc12SMatthew G. Knepley 
99720f4b53cSBarry Smith   Collective
998fb1bcc12SMatthew G. Knepley 
99960225df5SJacob Faibussowitsch   Input Parameters:
100020f4b53cSBarry Smith + dm        - a `DMSWARM`
100162741f57SDave May - fieldname - the textual name given to a registered field
1002fb1bcc12SMatthew G. Knepley 
100360225df5SJacob Faibussowitsch   Output Parameter:
1004fb1bcc12SMatthew G. Knepley . vec - the vector
1005fb1bcc12SMatthew G. Knepley 
1006fb1bcc12SMatthew G. Knepley   Level: beginner
1007fb1bcc12SMatthew G. Knepley 
100820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()`
1009fb1bcc12SMatthew G. Knepley @*/
1010d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec)
1011d71ae5a4SJacob Faibussowitsch {
1012fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
1013ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
10149566063dSJacob Faibussowitsch   PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec));
10153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1016bbe8250bSMatthew G. Knepley }
1017bbe8250bSMatthew G. Knepley 
1018cc4c1da9SBarry Smith /*@
101919307e5cSMatthew G. Knepley   DMSwarmCreateGlobalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set
102019307e5cSMatthew G. Knepley 
102119307e5cSMatthew G. Knepley   Collective
102219307e5cSMatthew G. Knepley 
102319307e5cSMatthew G. Knepley   Input Parameters:
102419307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
102519307e5cSMatthew G. Knepley . Nf         - the number of fields
102619307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
102719307e5cSMatthew G. Knepley 
102819307e5cSMatthew G. Knepley   Output Parameter:
102919307e5cSMatthew G. Knepley . vec - the vector
103019307e5cSMatthew G. Knepley 
103119307e5cSMatthew G. Knepley   Level: beginner
103219307e5cSMatthew G. Knepley 
103319307e5cSMatthew G. Knepley   Notes:
103419307e5cSMatthew G. Knepley   The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromFields()`.
103519307e5cSMatthew G. Knepley 
103619307e5cSMatthew G. Knepley   This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateGlobalVectorFromField()`
103719307e5cSMatthew G. Knepley 
103819307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromFields()`
103919307e5cSMatthew G. Knepley @*/
104019307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
104119307e5cSMatthew G. Knepley {
104219307e5cSMatthew G. Knepley   MPI_Comm comm = PetscObjectComm((PetscObject)dm);
104319307e5cSMatthew G. Knepley 
104419307e5cSMatthew G. Knepley   PetscFunctionBegin;
104519307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
104619307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec));
104719307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
104819307e5cSMatthew G. Knepley }
104919307e5cSMatthew G. Knepley 
105019307e5cSMatthew G. Knepley /*@
105119307e5cSMatthew G. Knepley   DMSwarmDestroyGlobalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set
105219307e5cSMatthew G. Knepley 
105319307e5cSMatthew G. Knepley   Collective
105419307e5cSMatthew G. Knepley 
105519307e5cSMatthew G. Knepley   Input Parameters:
105619307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
105719307e5cSMatthew G. Knepley . Nf         - the number of fields
105819307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
105919307e5cSMatthew G. Knepley 
106019307e5cSMatthew G. Knepley   Output Parameter:
106119307e5cSMatthew G. Knepley . vec - the vector
106219307e5cSMatthew G. Knepley 
106319307e5cSMatthew G. Knepley   Level: beginner
106419307e5cSMatthew G. Knepley 
106519307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()`
106619307e5cSMatthew G. Knepley @*/
106719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
106819307e5cSMatthew G. Knepley {
106919307e5cSMatthew G. Knepley   PetscFunctionBegin;
107019307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
107119307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec));
107219307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
107319307e5cSMatthew G. Knepley }
107419307e5cSMatthew G. Knepley 
107519307e5cSMatthew G. Knepley /*@
107619307e5cSMatthew G. Knepley   DMSwarmCreateLocalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set
107719307e5cSMatthew G. Knepley 
107819307e5cSMatthew G. Knepley   Collective
107919307e5cSMatthew G. Knepley 
108019307e5cSMatthew G. Knepley   Input Parameters:
108119307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
108219307e5cSMatthew G. Knepley . Nf         - the number of fields
108319307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
108419307e5cSMatthew G. Knepley 
108519307e5cSMatthew G. Knepley   Output Parameter:
108619307e5cSMatthew G. Knepley . vec - the vector
108719307e5cSMatthew G. Knepley 
108819307e5cSMatthew G. Knepley   Level: beginner
108919307e5cSMatthew G. Knepley 
109019307e5cSMatthew G. Knepley   Notes:
109119307e5cSMatthew G. Knepley   The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
109219307e5cSMatthew G. Knepley 
109319307e5cSMatthew G. Knepley   This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateLocalVectorFromField()`
109419307e5cSMatthew G. Knepley 
109519307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()`
109619307e5cSMatthew G. Knepley @*/
109719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
109819307e5cSMatthew G. Knepley {
109919307e5cSMatthew G. Knepley   MPI_Comm comm = PETSC_COMM_SELF;
110019307e5cSMatthew G. Knepley 
110119307e5cSMatthew G. Knepley   PetscFunctionBegin;
110219307e5cSMatthew G. Knepley   PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec));
110319307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
110419307e5cSMatthew G. Knepley }
110519307e5cSMatthew G. Knepley 
110619307e5cSMatthew G. Knepley /*@
110719307e5cSMatthew G. Knepley   DMSwarmDestroyLocalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set
110819307e5cSMatthew G. Knepley 
110919307e5cSMatthew G. Knepley   Collective
111019307e5cSMatthew G. Knepley 
111119307e5cSMatthew G. Knepley   Input Parameters:
111219307e5cSMatthew G. Knepley + dm         - a `DMSWARM`
111319307e5cSMatthew G. Knepley . Nf         - the number of fields
111419307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields
111519307e5cSMatthew G. Knepley 
111619307e5cSMatthew G. Knepley   Output Parameter:
111719307e5cSMatthew G. Knepley . vec - the vector
111819307e5cSMatthew G. Knepley 
111919307e5cSMatthew G. Knepley   Level: beginner
112019307e5cSMatthew G. Knepley 
112119307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromFields()`
112219307e5cSMatthew G. Knepley @*/
112319307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec)
112419307e5cSMatthew G. Knepley {
112519307e5cSMatthew G. Knepley   PetscFunctionBegin;
112619307e5cSMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
112719307e5cSMatthew G. Knepley   PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec));
112819307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
112919307e5cSMatthew G. Knepley }
113019307e5cSMatthew G. Knepley 
113119307e5cSMatthew G. Knepley /*@
113220f4b53cSBarry Smith   DMSwarmInitializeFieldRegister - Initiates the registration of fields to a `DMSWARM`
1133d3a51819SDave May 
113420f4b53cSBarry Smith   Collective
1135d3a51819SDave May 
113660225df5SJacob Faibussowitsch   Input Parameter:
113720f4b53cSBarry Smith . dm - a `DMSWARM`
1138d3a51819SDave May 
1139d3a51819SDave May   Level: beginner
1140d3a51819SDave May 
114120f4b53cSBarry Smith   Note:
114220f4b53cSBarry Smith   After all fields have been registered, you must call `DMSwarmFinalizeFieldRegister()`.
1143d3a51819SDave May 
114420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
1145db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1146d3a51819SDave May @*/
1147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
1148d71ae5a4SJacob Faibussowitsch {
11495f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
11503454631fSDave May 
1151521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1152cc651181SDave May   if (!swarm->field_registration_initialized) {
11535f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
1154da81f932SPierre Jolivet     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifier */
11559566063dSJacob Faibussowitsch     PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT));  /* used for communication */
1156cc651181SDave May   }
11573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11585f50eb2eSDave May }
11595f50eb2eSDave May 
116074d0cae8SMatthew G. Knepley /*@
116120f4b53cSBarry Smith   DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a `DMSWARM`
1162d3a51819SDave May 
116320f4b53cSBarry Smith   Collective
1164d3a51819SDave May 
116560225df5SJacob Faibussowitsch   Input Parameter:
116620f4b53cSBarry Smith . dm - a `DMSWARM`
1167d3a51819SDave May 
1168d3a51819SDave May   Level: beginner
1169d3a51819SDave May 
117020f4b53cSBarry Smith   Note:
117120f4b53cSBarry Smith   After `DMSwarmFinalizeFieldRegister()` has been called, no new fields can be defined on the `DMSWARM`.
1172d3a51819SDave May 
117320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`,
1174db781477SPatrick Sanan           `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1175d3a51819SDave May @*/
1176d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
1177d71ae5a4SJacob Faibussowitsch {
11785f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
11796845f8f5SDave May 
1180521f74f9SMatthew G. Knepley   PetscFunctionBegin;
118148a46eb9SPierre Jolivet   if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db));
1182f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
11833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11845f50eb2eSDave May }
11855f50eb2eSDave May 
118674d0cae8SMatthew G. Knepley /*@
118720f4b53cSBarry Smith   DMSwarmSetLocalSizes - Sets the length of all registered fields on the `DMSWARM`
1188d3a51819SDave May 
118920f4b53cSBarry Smith   Not Collective
1190d3a51819SDave May 
119160225df5SJacob Faibussowitsch   Input Parameters:
1192fca3fa51SMatthew G. Knepley + sw     - a `DMSWARM`
1193d3a51819SDave May . nlocal - the length of each registered field
119462741f57SDave May - buffer - the length of the buffer used to efficient dynamic re-sizing
1195d3a51819SDave May 
1196d3a51819SDave May   Level: beginner
1197d3a51819SDave May 
119820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`
1199d3a51819SDave May @*/
1200fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmSetLocalSizes(DM sw, PetscInt nlocal, PetscInt buffer)
1201d71ae5a4SJacob Faibussowitsch {
1202fca3fa51SMatthew G. Knepley   DM_Swarm   *swarm = (DM_Swarm *)sw->data;
1203fca3fa51SMatthew G. Knepley   PetscMPIInt rank;
1204fca3fa51SMatthew G. Knepley   PetscInt   *rankval;
12055f50eb2eSDave May 
1206521f74f9SMatthew G. Knepley   PetscFunctionBegin;
12079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0));
12089566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer));
12099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0));
1210fca3fa51SMatthew G. Knepley 
1211fca3fa51SMatthew G. Knepley   // Initialize values in pid and rank placeholders
1212fca3fa51SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sw), &rank));
1213fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
1214fca3fa51SMatthew G. Knepley   for (PetscInt p = 0; p < nlocal; p++) rankval[p] = rank;
1215fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, DMSwarmField_rank, NULL, NULL, (void **)&rankval));
1216fca3fa51SMatthew G. Knepley   /* TODO: [pid - use MPI_Scan] */
12173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12185f50eb2eSDave May }
12195f50eb2eSDave May 
122074d0cae8SMatthew G. Knepley /*@
122120f4b53cSBarry Smith   DMSwarmSetCellDM - Attaches a `DM` to a `DMSWARM`
1222d3a51819SDave May 
122320f4b53cSBarry Smith   Collective
1224d3a51819SDave May 
122560225df5SJacob Faibussowitsch   Input Parameters:
122619307e5cSMatthew G. Knepley + sw - a `DMSWARM`
122719307e5cSMatthew G. Knepley - dm - the `DM` to attach to the `DMSWARM`
1228d3a51819SDave May 
1229d3a51819SDave May   Level: beginner
1230d3a51819SDave May 
123120f4b53cSBarry Smith   Note:
123219307e5cSMatthew G. Knepley   The attached `DM` (dm) will be queried for point location and
123320f4b53cSBarry Smith   neighbor MPI-rank information if `DMSwarmMigrate()` is called.
1234d3a51819SDave May 
123520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()`
1236d3a51819SDave May @*/
123719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM sw, DM dm)
1238d71ae5a4SJacob Faibussowitsch {
123919307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
124019307e5cSMatthew G. Knepley   const char   *name;
124119307e5cSMatthew G. Knepley   char         *coordName;
1242d52c2f21SMatthew G. Knepley 
1243d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
1244d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
124519307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
124619307e5cSMatthew G. Knepley   PetscCall(PetscStrallocpy(DMSwarmPICField_coor, &coordName));
124719307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 1, (const char **)&coordName, &celldm));
124819307e5cSMatthew G. Knepley   PetscCall(PetscFree(coordName));
124919307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
125019307e5cSMatthew G. Knepley   PetscCall(DMSwarmAddCellDM(sw, celldm));
125119307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMDestroy(&celldm));
125219307e5cSMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(sw, name));
1253d52c2f21SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1254d52c2f21SMatthew G. Knepley }
1255d52c2f21SMatthew G. Knepley 
1256d52c2f21SMatthew G. Knepley /*@
125719307e5cSMatthew G. Knepley   DMSwarmGetCellDM - Fetches the active cell `DM`
1258d52c2f21SMatthew G. Knepley 
1259d52c2f21SMatthew G. Knepley   Collective
1260d52c2f21SMatthew G. Knepley 
1261d52c2f21SMatthew G. Knepley   Input Parameter:
1262d52c2f21SMatthew G. Knepley . sw - a `DMSWARM`
1263d52c2f21SMatthew G. Knepley 
126419307e5cSMatthew G. Knepley   Output Parameter:
126519307e5cSMatthew G. Knepley . dm - the active `DM` for the `DMSWARM`
126619307e5cSMatthew G. Knepley 
1267d52c2f21SMatthew G. Knepley   Level: beginner
1268d52c2f21SMatthew G. Knepley 
126919307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`
1270d52c2f21SMatthew G. Knepley @*/
127119307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM sw, DM *dm)
1272d52c2f21SMatthew G. Knepley {
1273d52c2f21SMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
127419307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
127519307e5cSMatthew G. Knepley 
127619307e5cSMatthew G. Knepley   PetscFunctionBegin;
1277fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
127819307e5cSMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)&celldm));
127919307e5cSMatthew G. Knepley   PetscCheck(celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "There is no cell DM named %s in this Swarm", swarm->activeCellDM);
128019307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetDM(celldm, dm));
128119307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
128219307e5cSMatthew G. Knepley }
128319307e5cSMatthew G. Knepley 
1284fca3fa51SMatthew G. Knepley /*@C
1285fca3fa51SMatthew G. Knepley   DMSwarmGetCellDMNames - Get the list of cell `DM` names
1286fca3fa51SMatthew G. Knepley 
1287fca3fa51SMatthew G. Knepley   Not collective
1288fca3fa51SMatthew G. Knepley 
1289fca3fa51SMatthew G. Knepley   Input Parameter:
1290fca3fa51SMatthew G. Knepley . sw - a `DMSWARM`
1291fca3fa51SMatthew G. Knepley 
1292fca3fa51SMatthew G. Knepley   Output Parameters:
1293fca3fa51SMatthew G. Knepley + Ndm     - the number of `DMSwarmCellDM` in the `DMSWARM`
1294fca3fa51SMatthew G. Knepley - celldms - the name of each `DMSwarmCellDM`
1295fca3fa51SMatthew G. Knepley 
1296fca3fa51SMatthew G. Knepley   Level: beginner
1297fca3fa51SMatthew G. Knepley 
1298fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmGetCellDMByName()`
1299fca3fa51SMatthew G. Knepley @*/
1300fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMNames(DM sw, PetscInt *Ndm, const char **celldms[])
1301fca3fa51SMatthew G. Knepley {
1302fca3fa51SMatthew G. Knepley   DM_Swarm       *swarm = (DM_Swarm *)sw->data;
1303fca3fa51SMatthew G. Knepley   PetscObjectList next  = swarm->cellDMs;
1304fca3fa51SMatthew G. Knepley   PetscInt        n     = 0;
1305fca3fa51SMatthew G. Knepley 
1306fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
1307fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1308fca3fa51SMatthew G. Knepley   PetscAssertPointer(Ndm, 2);
1309fca3fa51SMatthew G. Knepley   PetscAssertPointer(celldms, 3);
1310fca3fa51SMatthew G. Knepley   while (next) {
1311fca3fa51SMatthew G. Knepley     next = next->next;
1312fca3fa51SMatthew G. Knepley     ++n;
1313fca3fa51SMatthew G. Knepley   }
1314fca3fa51SMatthew G. Knepley   PetscCall(PetscMalloc1(n, celldms));
1315fca3fa51SMatthew G. Knepley   next = swarm->cellDMs;
1316fca3fa51SMatthew G. Knepley   n    = 0;
1317fca3fa51SMatthew G. Knepley   while (next) {
1318fca3fa51SMatthew G. Knepley     (*celldms)[n] = (const char *)next->obj->name;
1319fca3fa51SMatthew G. Knepley     next          = next->next;
1320fca3fa51SMatthew G. Knepley     ++n;
1321fca3fa51SMatthew G. Knepley   }
1322fca3fa51SMatthew G. Knepley   *Ndm = n;
1323fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1324fca3fa51SMatthew G. Knepley }
1325fca3fa51SMatthew G. Knepley 
132619307e5cSMatthew G. Knepley /*@
132719307e5cSMatthew G. Knepley   DMSwarmSetCellDMActive - Activates a cell `DM` for a `DMSWARM`
132819307e5cSMatthew G. Knepley 
132919307e5cSMatthew G. Knepley   Collective
133019307e5cSMatthew G. Knepley 
133119307e5cSMatthew G. Knepley   Input Parameters:
133219307e5cSMatthew G. Knepley + sw   - a `DMSWARM`
133319307e5cSMatthew G. Knepley - name - name of the cell `DM` to active for the `DMSWARM`
133419307e5cSMatthew G. Knepley 
133519307e5cSMatthew G. Knepley   Level: beginner
133619307e5cSMatthew G. Knepley 
133719307e5cSMatthew G. Knepley   Note:
133819307e5cSMatthew G. Knepley   The attached `DM` (dmcell) will be queried for point location and
133919307e5cSMatthew G. Knepley   neighbor MPI-rank information if `DMSwarmMigrate()` is called.
134019307e5cSMatthew G. Knepley 
134119307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
134219307e5cSMatthew G. Knepley @*/
134319307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDMActive(DM sw, const char name[])
134419307e5cSMatthew G. Knepley {
134519307e5cSMatthew G. Knepley   DM_Swarm     *swarm = (DM_Swarm *)sw->data;
134619307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
1347d52c2f21SMatthew G. Knepley 
1348d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
1349d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
135019307e5cSMatthew G. Knepley   PetscCall(PetscInfo(sw, "Setting cell DM to %s\n", name));
135119307e5cSMatthew G. Knepley   PetscCall(PetscFree(swarm->activeCellDM));
135219307e5cSMatthew G. Knepley   PetscCall(PetscStrallocpy(name, (char **)&swarm->activeCellDM));
135319307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
135419307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1355d52c2f21SMatthew G. Knepley }
135619307e5cSMatthew G. Knepley 
135719307e5cSMatthew G. Knepley /*@
135819307e5cSMatthew G. Knepley   DMSwarmGetCellDMActive - Returns the active cell `DM` for a `DMSWARM`
135919307e5cSMatthew G. Knepley 
136019307e5cSMatthew G. Knepley   Collective
136119307e5cSMatthew G. Knepley 
136219307e5cSMatthew G. Knepley   Input Parameter:
136319307e5cSMatthew G. Knepley . sw - a `DMSWARM`
136419307e5cSMatthew G. Knepley 
136519307e5cSMatthew G. Knepley   Output Parameter:
136619307e5cSMatthew G. Knepley . celldm - the active `DMSwarmCellDM`
136719307e5cSMatthew G. Knepley 
136819307e5cSMatthew G. Knepley   Level: beginner
136919307e5cSMatthew G. Knepley 
137019307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
137119307e5cSMatthew G. Knepley @*/
137219307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMActive(DM sw, DMSwarmCellDM *celldm)
137319307e5cSMatthew G. Knepley {
137419307e5cSMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
137519307e5cSMatthew G. Knepley 
137619307e5cSMatthew G. Knepley   PetscFunctionBegin;
137719307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1378fca3fa51SMatthew G. Knepley   PetscAssertPointer(celldm, 2);
137919307e5cSMatthew G. Knepley   PetscCheck(swarm->activeCellDM, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no active cell DM");
138019307e5cSMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)celldm));
1381fca3fa51SMatthew G. Knepley   PetscCheck(*celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no valid cell DM for %s", swarm->activeCellDM);
1382fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
1383fca3fa51SMatthew G. Knepley }
1384fca3fa51SMatthew G. Knepley 
1385fca3fa51SMatthew G. Knepley /*@C
1386fca3fa51SMatthew G. Knepley   DMSwarmGetCellDMByName - Get a `DMSwarmCellDM` from its name
1387fca3fa51SMatthew G. Knepley 
1388fca3fa51SMatthew G. Knepley   Not collective
1389fca3fa51SMatthew G. Knepley 
1390fca3fa51SMatthew G. Knepley   Input Parameters:
1391fca3fa51SMatthew G. Knepley + sw   - a `DMSWARM`
1392fca3fa51SMatthew G. Knepley - name - the name
1393fca3fa51SMatthew G. Knepley 
1394fca3fa51SMatthew G. Knepley   Output Parameter:
1395fca3fa51SMatthew G. Knepley . celldm - the `DMSwarmCellDM`
1396fca3fa51SMatthew G. Knepley 
1397fca3fa51SMatthew G. Knepley   Level: beginner
1398fca3fa51SMatthew G. Knepley 
1399fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmGetCellDMNames()`
1400fca3fa51SMatthew G. Knepley @*/
1401fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMByName(DM sw, const char name[], DMSwarmCellDM *celldm)
1402fca3fa51SMatthew G. Knepley {
1403fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
1404fca3fa51SMatthew G. Knepley 
1405fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
1406fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
1407fca3fa51SMatthew G. Knepley   PetscAssertPointer(name, 2);
1408fca3fa51SMatthew G. Knepley   PetscAssertPointer(celldm, 3);
1409fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectListFind(swarm->cellDMs, name, (PetscObject *)celldm));
1410fca3fa51SMatthew G. Knepley   PetscCheck(*celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no valid cell DM for %s", name);
141119307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
141219307e5cSMatthew G. Knepley }
141319307e5cSMatthew G. Knepley 
141419307e5cSMatthew G. Knepley /*@
141519307e5cSMatthew G. Knepley   DMSwarmAddCellDM - Adds a cell `DM` to the `DMSWARM`
141619307e5cSMatthew G. Knepley 
141719307e5cSMatthew G. Knepley   Collective
141819307e5cSMatthew G. Knepley 
141919307e5cSMatthew G. Knepley   Input Parameters:
142019307e5cSMatthew G. Knepley + sw     - a `DMSWARM`
142119307e5cSMatthew G. Knepley - celldm - the `DMSwarmCellDM`
142219307e5cSMatthew G. Knepley 
142319307e5cSMatthew G. Knepley   Level: beginner
142419307e5cSMatthew G. Knepley 
142519307e5cSMatthew G. Knepley   Note:
142619307e5cSMatthew G. Knepley   Cell DMs with the same name will share the cellid field
142719307e5cSMatthew G. Knepley 
142819307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmPushCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()`
142919307e5cSMatthew G. Knepley @*/
143019307e5cSMatthew G. Knepley PetscErrorCode DMSwarmAddCellDM(DM sw, DMSwarmCellDM celldm)
143119307e5cSMatthew G. Knepley {
143219307e5cSMatthew G. Knepley   DM_Swarm   *swarm = (DM_Swarm *)sw->data;
143319307e5cSMatthew G. Knepley   const char *name;
143419307e5cSMatthew G. Knepley   PetscInt    dim;
143519307e5cSMatthew G. Knepley   PetscBool   flg;
143619307e5cSMatthew G. Knepley   MPI_Comm    comm;
143719307e5cSMatthew G. Knepley 
143819307e5cSMatthew G. Knepley   PetscFunctionBegin;
143919307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
144019307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
144119307e5cSMatthew G. Knepley   PetscValidHeaderSpecific(celldm, DMSWARMCELLDM_CLASSID, 2);
144219307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
144319307e5cSMatthew G. Knepley   PetscCall(PetscObjectListAdd(&swarm->cellDMs, name, (PetscObject)celldm));
144419307e5cSMatthew G. Knepley   PetscCall(DMGetDimension(sw, &dim));
144519307e5cSMatthew G. Knepley   for (PetscInt f = 0; f < celldm->Nfc; ++f) {
144619307e5cSMatthew G. Knepley     PetscCall(DMSwarmDataFieldStringInList(celldm->coordFields[f], swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg));
144719307e5cSMatthew G. Knepley     if (!flg) {
144819307e5cSMatthew G. Knepley       PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->coordFields[f], dim, PETSC_DOUBLE));
144919307e5cSMatthew G. Knepley     } else {
145019307e5cSMatthew G. Knepley       PetscDataType dt;
145119307e5cSMatthew G. Knepley       PetscInt      bs;
145219307e5cSMatthew G. Knepley 
145319307e5cSMatthew G. Knepley       PetscCall(DMSwarmGetFieldInfo(sw, celldm->coordFields[f], &bs, &dt));
145419307e5cSMatthew 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);
145519307e5cSMatthew G. Knepley       PetscCheck(dt == PETSC_DOUBLE, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s has datatype %s != PETSC_DOUBLE", celldm->coordFields[f], PetscDataTypes[dt]);
145619307e5cSMatthew G. Knepley     }
145719307e5cSMatthew G. Knepley   }
145819307e5cSMatthew G. Knepley   // Assume that DMs with the same name share the cellid field
145919307e5cSMatthew G. Knepley   PetscCall(DMSwarmDataFieldStringInList(celldm->cellid, swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg));
146019307e5cSMatthew G. Knepley   if (!flg) {
146119307e5cSMatthew G. Knepley     PetscBool   isShell, isDummy;
146219307e5cSMatthew G. Knepley     const char *name;
146319307e5cSMatthew G. Knepley 
146419307e5cSMatthew G. Knepley     // Allow dummy DMSHELL (I don't think we should support this mode)
146519307e5cSMatthew G. Knepley     PetscCall(PetscObjectTypeCompare((PetscObject)celldm->dm, DMSHELL, &isShell));
146619307e5cSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)celldm->dm, &name));
146719307e5cSMatthew G. Knepley     PetscCall(PetscStrcmp(name, "dummy", &isDummy));
146819307e5cSMatthew G. Knepley     if (!isShell || !isDummy) PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->cellid, 1, PETSC_INT));
146919307e5cSMatthew G. Knepley   }
147019307e5cSMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(sw, name));
14713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1472fe39f135SDave May }
1473fe39f135SDave May 
147474d0cae8SMatthew G. Knepley /*@
1475d5b43468SJose E. Roman   DMSwarmGetLocalSize - Retrieves the local length of fields registered
1476d3a51819SDave May 
147720f4b53cSBarry Smith   Not Collective
1478d3a51819SDave May 
147960225df5SJacob Faibussowitsch   Input Parameter:
148020f4b53cSBarry Smith . dm - a `DMSWARM`
1481d3a51819SDave May 
148260225df5SJacob Faibussowitsch   Output Parameter:
1483d3a51819SDave May . nlocal - the length of each registered field
1484d3a51819SDave May 
1485d3a51819SDave May   Level: beginner
1486d3a51819SDave May 
148720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()`
1488d3a51819SDave May @*/
1489d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal)
1490d71ae5a4SJacob Faibussowitsch {
1491dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1492dcf43ee8SDave May 
1493521f74f9SMatthew G. Knepley   PetscFunctionBegin;
14949566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL));
14953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1496dcf43ee8SDave May }
1497dcf43ee8SDave May 
149874d0cae8SMatthew G. Knepley /*@
1499d5b43468SJose E. Roman   DMSwarmGetSize - Retrieves the total length of fields registered
1500d3a51819SDave May 
150120f4b53cSBarry Smith   Collective
1502d3a51819SDave May 
150360225df5SJacob Faibussowitsch   Input Parameter:
150420f4b53cSBarry Smith . dm - a `DMSWARM`
1505d3a51819SDave May 
150660225df5SJacob Faibussowitsch   Output Parameter:
1507d3a51819SDave May . n - the total length of each registered field
1508d3a51819SDave May 
1509d3a51819SDave May   Level: beginner
1510d3a51819SDave May 
1511d3a51819SDave May   Note:
151220f4b53cSBarry Smith   This calls `MPI_Allreduce()` upon each call (inefficient but safe)
1513d3a51819SDave May 
151420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()`
1515d3a51819SDave May @*/
1516d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n)
1517d71ae5a4SJacob Faibussowitsch {
1518dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
15195627991aSBarry Smith   PetscInt  nlocal;
1520dcf43ee8SDave May 
1521521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15229566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1523462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
15243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1525dcf43ee8SDave May }
1526dcf43ee8SDave May 
1527ce78bad3SBarry Smith /*@C
152820f4b53cSBarry Smith   DMSwarmRegisterPetscDatatypeField - Register a field to a `DMSWARM` with a native PETSc data type
1529d3a51819SDave May 
153020f4b53cSBarry Smith   Collective
1531d3a51819SDave May 
153260225df5SJacob Faibussowitsch   Input Parameters:
153320f4b53cSBarry Smith + dm        - a `DMSWARM`
1534d3a51819SDave May . fieldname - the textual name to identify this field
1535d3a51819SDave May . blocksize - the number of each data type
153620f4b53cSBarry Smith - type      - a valid PETSc data type (`PETSC_CHAR`, `PETSC_SHORT`, `PETSC_INT`, `PETSC_FLOAT`, `PETSC_REAL`, `PETSC_LONG`)
1537d3a51819SDave May 
1538d3a51819SDave May   Level: beginner
1539d3a51819SDave May 
1540d3a51819SDave May   Notes:
15418b8a3813SDave May   The textual name for each registered field must be unique.
1542d3a51819SDave May 
154320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()`
1544d3a51819SDave May @*/
1545d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type)
1546d71ae5a4SJacob Faibussowitsch {
1547b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1548b62e03f8SDave May   size_t    size;
1549b62e03f8SDave May 
1550521f74f9SMatthew G. Knepley   PetscFunctionBegin;
155128b400f6SJacob Faibussowitsch   PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first");
155228b400f6SJacob Faibussowitsch   PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
15535f50eb2eSDave May 
155408401ef6SPierre Jolivet   PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
155508401ef6SPierre Jolivet   PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
155608401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
155708401ef6SPierre Jolivet   PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
155808401ef6SPierre Jolivet   PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}");
1559b62e03f8SDave May 
15609566063dSJacob Faibussowitsch   PetscCall(PetscDataTypeGetSize(type, &size));
1561b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
15629566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL));
156352c3ed93SDave May   {
156477048351SPatrick Sanan     DMSwarmDataField gfield;
156552c3ed93SDave May 
15669566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
15679566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
156852c3ed93SDave May   }
1569b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = type;
15703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1571b62e03f8SDave May }
1572b62e03f8SDave May 
1573d3a51819SDave May /*@C
157420f4b53cSBarry Smith   DMSwarmRegisterUserStructField - Register a user defined struct to a `DMSWARM`
1575d3a51819SDave May 
157620f4b53cSBarry Smith   Collective
1577d3a51819SDave May 
157860225df5SJacob Faibussowitsch   Input Parameters:
157920f4b53cSBarry Smith + dm        - a `DMSWARM`
1580d3a51819SDave May . fieldname - the textual name to identify this field
158162741f57SDave May - size      - the size in bytes of the user struct of each data type
1582d3a51819SDave May 
1583d3a51819SDave May   Level: beginner
1584d3a51819SDave May 
158520f4b53cSBarry Smith   Note:
15868b8a3813SDave May   The textual name for each registered field must be unique.
1587d3a51819SDave May 
158820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()`
1589d3a51819SDave May @*/
1590d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size)
1591d71ae5a4SJacob Faibussowitsch {
1592b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1593b62e03f8SDave May 
1594521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15959566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL));
1596b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT;
15973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1598b62e03f8SDave May }
1599b62e03f8SDave May 
1600d3a51819SDave May /*@C
160120f4b53cSBarry Smith   DMSwarmRegisterUserDatatypeField - Register a user defined data type to a `DMSWARM`
1602d3a51819SDave May 
160320f4b53cSBarry Smith   Collective
1604d3a51819SDave May 
160560225df5SJacob Faibussowitsch   Input Parameters:
160620f4b53cSBarry Smith + dm        - a `DMSWARM`
1607d3a51819SDave May . fieldname - the textual name to identify this field
1608d3a51819SDave May . size      - the size in bytes of the user data type
160962741f57SDave May - blocksize - the number of each data type
1610d3a51819SDave May 
1611d3a51819SDave May   Level: beginner
1612d3a51819SDave May 
161320f4b53cSBarry Smith   Note:
16148b8a3813SDave May   The textual name for each registered field must be unique.
1615d3a51819SDave May 
161642747ad1SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()`
1617d3a51819SDave May @*/
1618d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize)
1619d71ae5a4SJacob Faibussowitsch {
1620b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1621b62e03f8SDave May 
1622521f74f9SMatthew G. Knepley   PetscFunctionBegin;
16239566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL));
1624320740a0SDave May   {
162577048351SPatrick Sanan     DMSwarmDataField gfield;
1626320740a0SDave May 
16279566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
16289566063dSJacob Faibussowitsch     PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize));
1629320740a0SDave May   }
1630b62e03f8SDave May   swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
16313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1632b62e03f8SDave May }
1633b62e03f8SDave May 
1634d3a51819SDave May /*@C
1635d3a51819SDave May   DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1636d3a51819SDave May 
1637cc4c1da9SBarry Smith   Not Collective, No Fortran Support
1638d3a51819SDave May 
163960225df5SJacob Faibussowitsch   Input Parameters:
164020f4b53cSBarry Smith + dm        - a `DMSWARM`
164162741f57SDave May - fieldname - the textual name to identify this field
1642d3a51819SDave May 
164360225df5SJacob Faibussowitsch   Output Parameters:
164462741f57SDave May + blocksize - the number of each data type
1645d3a51819SDave May . type      - the data type
164662741f57SDave May - data      - pointer to raw array
1647d3a51819SDave May 
1648d3a51819SDave May   Level: beginner
1649d3a51819SDave May 
1650d3a51819SDave May   Notes:
165120f4b53cSBarry Smith   The array must be returned using a matching call to `DMSwarmRestoreField()`.
1652d3a51819SDave May 
1653ce78bad3SBarry Smith   Fortran Note:
1654ce78bad3SBarry Smith   Only works for `type` of `PETSC_SCALAR`
1655ce78bad3SBarry Smith 
165620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreField()`
1657d3a51819SDave May @*/
1658ce78bad3SBarry Smith PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) PeNS
1659d71ae5a4SJacob Faibussowitsch {
1660b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
166177048351SPatrick Sanan   DMSwarmDataField gfield;
1662b62e03f8SDave May 
1663521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1664ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
16659566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
16669566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
16679566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetAccess(gfield));
16689566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldGetEntries(gfield, data));
1669ad540459SPierre Jolivet   if (blocksize) *blocksize = gfield->bs;
1670ad540459SPierre Jolivet   if (type) *type = gfield->petsc_type;
16713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1672b62e03f8SDave May }
1673b62e03f8SDave May 
1674d3a51819SDave May /*@C
1675d3a51819SDave May   DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1676d3a51819SDave May 
1677ce78bad3SBarry Smith   Not Collective
1678d3a51819SDave May 
167960225df5SJacob Faibussowitsch   Input Parameters:
168020f4b53cSBarry Smith + dm        - a `DMSWARM`
168162741f57SDave May - fieldname - the textual name to identify this field
1682d3a51819SDave May 
168360225df5SJacob Faibussowitsch   Output Parameters:
168462741f57SDave May + blocksize - the number of each data type
1685d3a51819SDave May . type      - the data type
168662741f57SDave May - data      - pointer to raw array
1687d3a51819SDave May 
1688d3a51819SDave May   Level: beginner
1689d3a51819SDave May 
1690d3a51819SDave May   Notes:
169120f4b53cSBarry Smith   The user must call `DMSwarmGetField()` prior to calling `DMSwarmRestoreField()`.
1692d3a51819SDave May 
1693ce78bad3SBarry Smith   Fortran Note:
1694ce78bad3SBarry Smith   Only works for `type` of `PETSC_SCALAR`
1695ce78bad3SBarry Smith 
169620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetField()`
1697d3a51819SDave May @*/
1698ce78bad3SBarry Smith PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) PeNS
1699d71ae5a4SJacob Faibussowitsch {
1700b62e03f8SDave May   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
170177048351SPatrick Sanan   DMSwarmDataField gfield;
1702b62e03f8SDave May 
1703521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1704ea7032a0SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
17059566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
17069566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataFieldRestoreAccess(gfield));
1707b62e03f8SDave May   if (data) *data = NULL;
17083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1709b62e03f8SDave May }
1710b62e03f8SDave May 
17110bf7c1c5SMatthew G. Knepley PetscErrorCode DMSwarmGetFieldInfo(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type)
17120bf7c1c5SMatthew G. Knepley {
17130bf7c1c5SMatthew G. Knepley   DM_Swarm        *swarm = (DM_Swarm *)dm->data;
17140bf7c1c5SMatthew G. Knepley   DMSwarmDataField gfield;
17150bf7c1c5SMatthew G. Knepley 
17160bf7c1c5SMatthew G. Knepley   PetscFunctionBegin;
17170bf7c1c5SMatthew G. Knepley   PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM);
17180bf7c1c5SMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield));
17190bf7c1c5SMatthew G. Knepley   if (blocksize) *blocksize = gfield->bs;
17200bf7c1c5SMatthew G. Knepley   if (type) *type = gfield->petsc_type;
17210bf7c1c5SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
17220bf7c1c5SMatthew G. Knepley }
17230bf7c1c5SMatthew G. Knepley 
172474d0cae8SMatthew G. Knepley /*@
172520f4b53cSBarry Smith   DMSwarmAddPoint - Add space for one new point in the `DMSWARM`
1726d3a51819SDave May 
172720f4b53cSBarry Smith   Not Collective
1728d3a51819SDave May 
172960225df5SJacob Faibussowitsch   Input Parameter:
173020f4b53cSBarry Smith . dm - a `DMSWARM`
1731d3a51819SDave May 
1732d3a51819SDave May   Level: beginner
1733d3a51819SDave May 
1734d3a51819SDave May   Notes:
17358b8a3813SDave May   The new point will have all fields initialized to zero.
1736d3a51819SDave May 
173720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddNPoints()`
1738d3a51819SDave May @*/
1739d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddPoint(DM dm)
1740d71ae5a4SJacob Faibussowitsch {
1741cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1742cb1d1399SDave May 
1743521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17449566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
17459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
17469566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketAddPoint(swarm->db));
17479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
17483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1749cb1d1399SDave May }
1750cb1d1399SDave May 
175174d0cae8SMatthew G. Knepley /*@
175220f4b53cSBarry Smith   DMSwarmAddNPoints - Add space for a number of new points in the `DMSWARM`
1753d3a51819SDave May 
175420f4b53cSBarry Smith   Not Collective
1755d3a51819SDave May 
175660225df5SJacob Faibussowitsch   Input Parameters:
175720f4b53cSBarry Smith + dm      - a `DMSWARM`
175862741f57SDave May - npoints - the number of new points to add
1759d3a51819SDave May 
1760d3a51819SDave May   Level: beginner
1761d3a51819SDave May 
1762d3a51819SDave May   Notes:
17638b8a3813SDave May   The new point will have all fields initialized to zero.
1764d3a51819SDave May 
176520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddPoint()`
1766d3a51819SDave May @*/
1767d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints)
1768d71ae5a4SJacob Faibussowitsch {
1769cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1770cb1d1399SDave May   PetscInt  nlocal;
1771cb1d1399SDave May 
1772521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0));
17749566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL));
1775cb1d1399SDave May   nlocal = nlocal + npoints;
17769566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT));
17779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0));
17783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1779cb1d1399SDave May }
1780cb1d1399SDave May 
178174d0cae8SMatthew G. Knepley /*@
178220f4b53cSBarry Smith   DMSwarmRemovePoint - Remove the last point from the `DMSWARM`
1783d3a51819SDave May 
178420f4b53cSBarry Smith   Not Collective
1785d3a51819SDave May 
178660225df5SJacob Faibussowitsch   Input Parameter:
178720f4b53cSBarry Smith . dm - a `DMSWARM`
1788d3a51819SDave May 
1789d3a51819SDave May   Level: beginner
1790d3a51819SDave May 
179120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePointAtIndex()`
1792d3a51819SDave May @*/
1793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePoint(DM dm)
1794d71ae5a4SJacob Faibussowitsch {
1795cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1796cb1d1399SDave May 
1797521f74f9SMatthew G. Knepley   PetscFunctionBegin;
17989566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
17999566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePoint(swarm->db));
18009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
18013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1802cb1d1399SDave May }
1803cb1d1399SDave May 
180474d0cae8SMatthew G. Knepley /*@
180520f4b53cSBarry Smith   DMSwarmRemovePointAtIndex - Removes a specific point from the `DMSWARM`
1806d3a51819SDave May 
180720f4b53cSBarry Smith   Not Collective
1808d3a51819SDave May 
180960225df5SJacob Faibussowitsch   Input Parameters:
181020f4b53cSBarry Smith + dm  - a `DMSWARM`
181162741f57SDave May - idx - index of point to remove
1812d3a51819SDave May 
1813d3a51819SDave May   Level: beginner
1814d3a51819SDave May 
181520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()`
1816d3a51819SDave May @*/
1817d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx)
1818d71ae5a4SJacob Faibussowitsch {
1819cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1820cb1d1399SDave May 
1821521f74f9SMatthew G. Knepley   PetscFunctionBegin;
18229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0));
18239566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx));
18249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0));
18253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1826cb1d1399SDave May }
1827b62e03f8SDave May 
182874d0cae8SMatthew G. Knepley /*@
182920f4b53cSBarry Smith   DMSwarmCopyPoint - Copy point pj to point pi in the `DMSWARM`
1830ba4fc9c6SDave May 
183120f4b53cSBarry Smith   Not Collective
1832ba4fc9c6SDave May 
183360225df5SJacob Faibussowitsch   Input Parameters:
183420f4b53cSBarry Smith + dm - a `DMSWARM`
1835ba4fc9c6SDave May . pi - the index of the point to copy
1836ba4fc9c6SDave May - pj - the point index where the copy should be located
1837ba4fc9c6SDave May 
1838ba4fc9c6SDave May   Level: beginner
1839ba4fc9c6SDave May 
184020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()`
1841ba4fc9c6SDave May @*/
1842d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj)
1843d71ae5a4SJacob Faibussowitsch {
1844ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1845ba4fc9c6SDave May 
1846ba4fc9c6SDave May   PetscFunctionBegin;
18479566063dSJacob Faibussowitsch   if (!swarm->issetup) PetscCall(DMSetUp(dm));
18489566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj));
18493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1850ba4fc9c6SDave May }
1851ba4fc9c6SDave May 
185266976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points)
1853d71ae5a4SJacob Faibussowitsch {
1854521f74f9SMatthew G. Knepley   PetscFunctionBegin;
18559566063dSJacob Faibussowitsch   PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points));
18563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18573454631fSDave May }
18583454631fSDave May 
185974d0cae8SMatthew G. Knepley /*@
186020f4b53cSBarry Smith   DMSwarmMigrate - Relocates points defined in the `DMSWARM` to other MPI-ranks
1861d3a51819SDave May 
186220f4b53cSBarry Smith   Collective
1863d3a51819SDave May 
186460225df5SJacob Faibussowitsch   Input Parameters:
186520f4b53cSBarry Smith + dm                 - the `DMSWARM`
186662741f57SDave May - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1867d3a51819SDave May 
1868d3a51819SDave May   Level: advanced
1869d3a51819SDave May 
187020f4b53cSBarry Smith   Notes:
187120f4b53cSBarry Smith   The `DM` will be modified to accommodate received points.
187220f4b53cSBarry Smith   If `remove_sent_points` is `PETSC_TRUE`, any points that were sent will be removed from the `DM`.
187320f4b53cSBarry Smith   Different styles of migration are supported. See `DMSwarmSetMigrateType()`.
187420f4b53cSBarry Smith 
187520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`
1876d3a51819SDave May @*/
1877d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points)
1878d71ae5a4SJacob Faibussowitsch {
1879f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
1880f0cdbbbaSDave May 
1881521f74f9SMatthew G. Knepley   PetscFunctionBegin;
18829566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0));
1883f0cdbbbaSDave May   switch (swarm->migrate_type) {
1884d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_BASIC:
1885d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points));
1886d71ae5a4SJacob Faibussowitsch     break;
1887d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLNSCATTER:
1888d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points));
1889d71ae5a4SJacob Faibussowitsch     break;
1890d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_DMCELLEXACT:
1891d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1892d71ae5a4SJacob Faibussowitsch   case DMSWARM_MIGRATE_USER:
1893d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented");
1894d71ae5a4SJacob Faibussowitsch   default:
1895d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown");
1896f0cdbbbaSDave May   }
18979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0));
18989566063dSJacob Faibussowitsch   PetscCall(DMClearGlobalVectors(dm));
18993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19003454631fSDave May }
19013454631fSDave May 
1902f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize);
1903f0cdbbbaSDave May 
1904d3a51819SDave May /*
1905d3a51819SDave May  DMSwarmCollectViewCreate
1906d3a51819SDave May 
1907d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1908d3a51819SDave May 
1909d3a51819SDave May  Notes:
19108b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1911d3a51819SDave May  they have finished computations associated with the collected points
1912d3a51819SDave May */
1913d3a51819SDave May 
191474d0cae8SMatthew G. Knepley /*@
1915d3a51819SDave May   DMSwarmCollectViewCreate - Applies a collection method and gathers points
191620f4b53cSBarry Smith   in neighbour ranks into the `DMSWARM`
1917d3a51819SDave May 
191820f4b53cSBarry Smith   Collective
1919d3a51819SDave May 
192060225df5SJacob Faibussowitsch   Input Parameter:
192120f4b53cSBarry Smith . dm - the `DMSWARM`
1922d3a51819SDave May 
1923d3a51819SDave May   Level: advanced
1924d3a51819SDave May 
192520f4b53cSBarry Smith   Notes:
192620f4b53cSBarry Smith   Users should call `DMSwarmCollectViewDestroy()` after
192720f4b53cSBarry Smith   they have finished computations associated with the collected points
19280764c050SBarry Smith 
192920f4b53cSBarry Smith   Different collect methods are supported. See `DMSwarmSetCollectType()`.
193020f4b53cSBarry Smith 
19310764c050SBarry Smith   Developer Note:
19320764c050SBarry Smith   Create and Destroy routines create new objects that can get destroyed, they do not change the state
19330764c050SBarry Smith   of the current object.
19340764c050SBarry Smith 
193520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()`
1936d3a51819SDave May @*/
1937d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewCreate(DM dm)
1938d71ae5a4SJacob Faibussowitsch {
19392712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
19402712d1f2SDave May   PetscInt  ng;
19412712d1f2SDave May 
1942521f74f9SMatthew G. Knepley   PetscFunctionBegin;
194328b400f6SJacob Faibussowitsch   PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active");
19449566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &ng));
1945480eef7bSDave May   switch (swarm->collect_type) {
1946d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_BASIC:
1947d71ae5a4SJacob Faibussowitsch     PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng));
1948d71ae5a4SJacob Faibussowitsch     break;
1949d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1950d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1951d71ae5a4SJacob Faibussowitsch   case DMSWARM_COLLECT_GENERAL:
1952d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented");
1953d71ae5a4SJacob Faibussowitsch   default:
1954d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown");
1955480eef7bSDave May   }
1956480eef7bSDave May   swarm->collect_view_active       = PETSC_TRUE;
1957480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
19583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19592712d1f2SDave May }
19602712d1f2SDave May 
196174d0cae8SMatthew G. Knepley /*@
196220f4b53cSBarry Smith   DMSwarmCollectViewDestroy - Resets the `DMSWARM` to the size prior to calling `DMSwarmCollectViewCreate()`
1963d3a51819SDave May 
196420f4b53cSBarry Smith   Collective
1965d3a51819SDave May 
196660225df5SJacob Faibussowitsch   Input Parameters:
196720f4b53cSBarry Smith . dm - the `DMSWARM`
1968d3a51819SDave May 
1969d3a51819SDave May   Notes:
197020f4b53cSBarry Smith   Users should call `DMSwarmCollectViewCreate()` before this function is called.
1971d3a51819SDave May 
1972d3a51819SDave May   Level: advanced
1973d3a51819SDave May 
19740764c050SBarry Smith   Developer Note:
19750764c050SBarry Smith   Create and Destroy routines create new objects that can get destroyed, they do not change the state
19760764c050SBarry Smith   of the current object.
19770764c050SBarry Smith 
197820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()`
1979d3a51819SDave May @*/
1980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
1981d71ae5a4SJacob Faibussowitsch {
19822712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
19832712d1f2SDave May 
1984521f74f9SMatthew G. Knepley   PetscFunctionBegin;
198528b400f6SJacob Faibussowitsch   PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active");
19869566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1));
1987480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
19883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19892712d1f2SDave May }
19903454631fSDave May 
199166976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmSetUpPIC(DM dm)
1992d71ae5a4SJacob Faibussowitsch {
1993f0cdbbbaSDave May   PetscInt dim;
1994f0cdbbbaSDave May 
1995521f74f9SMatthew G. Knepley   PetscFunctionBegin;
19969566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetNumSpecies(dm, 1));
19979566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
199863a3b9bcSJacob Faibussowitsch   PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
199963a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim);
20003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2001f0cdbbbaSDave May }
2002f0cdbbbaSDave May 
200374d0cae8SMatthew G. Knepley /*@
200431403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
200531403186SMatthew G. Knepley 
200620f4b53cSBarry Smith   Collective
200731403186SMatthew G. Knepley 
200860225df5SJacob Faibussowitsch   Input Parameters:
200920f4b53cSBarry Smith + dm  - the `DMSWARM`
201020f4b53cSBarry Smith - Npc - The number of particles per cell in the cell `DM`
201131403186SMatthew G. Knepley 
201231403186SMatthew G. Knepley   Level: intermediate
201331403186SMatthew G. Knepley 
201420f4b53cSBarry Smith   Notes:
201520f4b53cSBarry Smith   The user must use `DMSwarmSetCellDM()` to set the cell `DM` first. The particles are placed randomly inside each cell. If only
201620f4b53cSBarry Smith   one particle is in each cell, it is placed at the centroid.
201720f4b53cSBarry Smith 
201820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`
201931403186SMatthew G. Knepley @*/
2020d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
2021d71ae5a4SJacob Faibussowitsch {
202231403186SMatthew G. Knepley   DM             cdm;
202319307e5cSMatthew G. Knepley   DMSwarmCellDM  celldm;
202431403186SMatthew G. Knepley   PetscRandom    rnd;
202531403186SMatthew G. Knepley   DMPolytopeType ct;
202631403186SMatthew G. Knepley   PetscBool      simplex;
202731403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
202819307e5cSMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p, Nfc;
202919307e5cSMatthew G. Knepley   const char   **coordFields;
203031403186SMatthew G. Knepley 
203131403186SMatthew G. Knepley   PetscFunctionBeginUser;
20329566063dSJacob Faibussowitsch   PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd));
20339566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0));
20349566063dSJacob Faibussowitsch   PetscCall(PetscRandomSetType(rnd, PETSCRAND48));
203531403186SMatthew G. Knepley 
203619307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
203719307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
203819307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
20399566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
20409566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(cdm, &dim));
20419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd));
20429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(cdm, cStart, &ct));
204331403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
204431403186SMatthew G. Knepley 
20459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ));
204631403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
204719307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, coordFields[0], NULL, NULL, (void **)&coords));
204831403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
204931403186SMatthew G. Knepley     if (Npc == 1) {
20509566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL));
205131403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d];
205231403186SMatthew G. Knepley     } else {
20539566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */
205431403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
205531403186SMatthew G. Knepley         const PetscInt n   = c * Npc + p;
205631403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
205731403186SMatthew G. Knepley 
205831403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
20599566063dSJacob Faibussowitsch           PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d]));
206031403186SMatthew G. Knepley           sum += refcoords[d];
206131403186SMatthew G. Knepley         }
20629371c9d4SSatish Balay         if (simplex && sum > 0.0)
20639371c9d4SSatish Balay           for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum;
206431403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]);
206531403186SMatthew G. Knepley       }
206631403186SMatthew G. Knepley     }
206731403186SMatthew G. Knepley   }
206819307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, coordFields[0], NULL, NULL, (void **)&coords));
20699566063dSJacob Faibussowitsch   PetscCall(PetscFree5(centroid, xi0, v0, J, invJ));
20709566063dSJacob Faibussowitsch   PetscCall(PetscRandomDestroy(&rnd));
20713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207231403186SMatthew G. Knepley }
207331403186SMatthew G. Knepley 
207431403186SMatthew G. Knepley /*@
2075fca3fa51SMatthew G. Knepley   DMSwarmGetType - Get particular flavor of `DMSWARM`
2076fca3fa51SMatthew G. Knepley 
2077fca3fa51SMatthew G. Knepley   Collective
2078fca3fa51SMatthew G. Knepley 
2079fca3fa51SMatthew G. Knepley   Input Parameter:
2080fca3fa51SMatthew G. Knepley . sw - the `DMSWARM`
2081fca3fa51SMatthew G. Knepley 
2082fca3fa51SMatthew G. Knepley   Output Parameter:
2083fca3fa51SMatthew G. Knepley . stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`)
2084fca3fa51SMatthew G. Knepley 
2085fca3fa51SMatthew G. Knepley   Level: advanced
2086fca3fa51SMatthew G. Knepley 
2087fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC`
2088fca3fa51SMatthew G. Knepley @*/
2089fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetType(DM sw, DMSwarmType *stype)
2090fca3fa51SMatthew G. Knepley {
2091fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
2092fca3fa51SMatthew G. Knepley 
2093fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2094fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
2095fca3fa51SMatthew G. Knepley   PetscAssertPointer(stype, 2);
2096fca3fa51SMatthew G. Knepley   *stype = swarm->swarm_type;
2097fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2098fca3fa51SMatthew G. Knepley }
2099fca3fa51SMatthew G. Knepley 
2100fca3fa51SMatthew G. Knepley /*@
210120f4b53cSBarry Smith   DMSwarmSetType - Set particular flavor of `DMSWARM`
2102d3a51819SDave May 
210320f4b53cSBarry Smith   Collective
2104d3a51819SDave May 
210560225df5SJacob Faibussowitsch   Input Parameters:
2106fca3fa51SMatthew G. Knepley + sw    - the `DMSWARM`
210720f4b53cSBarry Smith - stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`)
2108d3a51819SDave May 
2109d3a51819SDave May   Level: advanced
2110d3a51819SDave May 
211120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC`
2112d3a51819SDave May @*/
2113fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM sw, DMSwarmType stype)
2114d71ae5a4SJacob Faibussowitsch {
2115fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
2116f0cdbbbaSDave May 
2117521f74f9SMatthew G. Knepley   PetscFunctionBegin;
2118fca3fa51SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
2119f0cdbbbaSDave May   swarm->swarm_type = stype;
2120fca3fa51SMatthew G. Knepley   if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(sw));
21213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2122f0cdbbbaSDave May }
2123f0cdbbbaSDave May 
2124fca3fa51SMatthew G. Knepley static PetscErrorCode DMSwarmCreateRemapDM_Private(DM sw, DM *rdm)
2125d71ae5a4SJacob Faibussowitsch {
2126fca3fa51SMatthew G. Knepley   PetscFE        fe;
2127fca3fa51SMatthew G. Knepley   DMPolytopeType ct;
2128fca3fa51SMatthew G. Knepley   PetscInt       dim, cStart;
2129fca3fa51SMatthew G. Knepley   const char    *prefix = "remap_";
2130fca3fa51SMatthew G. Knepley 
2131fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2132fca3fa51SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), rdm));
2133fca3fa51SMatthew G. Knepley   PetscCall(DMSetType(*rdm, DMPLEX));
2134fca3fa51SMatthew G. Knepley   PetscCall(DMPlexSetOptionsPrefix(*rdm, prefix));
2135fca3fa51SMatthew G. Knepley   PetscCall(DMSetFromOptions(*rdm));
2136fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*rdm, "remap"));
2137fca3fa51SMatthew G. Knepley   PetscCall(DMViewFromOptions(*rdm, NULL, "-dm_view"));
2138fca3fa51SMatthew G. Knepley 
2139fca3fa51SMatthew G. Knepley   PetscCall(DMGetDimension(*rdm, &dim));
2140fca3fa51SMatthew G. Knepley   PetscCall(DMPlexGetHeightStratum(*rdm, 0, &cStart, NULL));
2141fca3fa51SMatthew G. Knepley   PetscCall(DMPlexGetCellType(*rdm, cStart, &ct));
2142fca3fa51SMatthew G. Knepley   PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, prefix, PETSC_DETERMINE, &fe));
2143fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)fe, "distribution"));
2144fca3fa51SMatthew G. Knepley   PetscCall(DMSetField(*rdm, 0, NULL, (PetscObject)fe));
2145fca3fa51SMatthew G. Knepley   PetscCall(DMCreateDS(*rdm));
2146fca3fa51SMatthew G. Knepley   PetscCall(PetscFEDestroy(&fe));
2147fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2148fca3fa51SMatthew G. Knepley }
2149fca3fa51SMatthew G. Knepley 
2150fca3fa51SMatthew G. Knepley static PetscErrorCode DMSetup_Swarm(DM sw)
2151fca3fa51SMatthew G. Knepley {
2152fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)sw->data;
21533454631fSDave May 
2154521f74f9SMatthew G. Knepley   PetscFunctionBegin;
21553ba16761SJacob Faibussowitsch   if (swarm->issetup) PetscFunctionReturn(PETSC_SUCCESS);
21563454631fSDave May   swarm->issetup = PETSC_TRUE;
21573454631fSDave May 
2158fca3fa51SMatthew G. Knepley   if (swarm->remap_type != DMSWARM_REMAP_NONE) {
2159fca3fa51SMatthew G. Knepley     DMSwarmCellDM celldm;
2160fca3fa51SMatthew G. Knepley     DM            rdm;
2161fca3fa51SMatthew G. Knepley     const char   *fieldnames[2]  = {DMSwarmPICField_coor, "velocity"};
2162fca3fa51SMatthew G. Knepley     const char   *vfieldnames[1] = {"w_q"};
2163fca3fa51SMatthew G. Knepley 
2164fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCreateRemapDM_Private(sw, &rdm));
2165fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMCreate(rdm, 1, vfieldnames, 2, fieldnames, &celldm));
2166fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmAddCellDM(sw, celldm));
2167fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMDestroy(&celldm));
2168fca3fa51SMatthew G. Knepley     PetscCall(DMDestroy(&rdm));
2169fca3fa51SMatthew G. Knepley   }
2170fca3fa51SMatthew G. Knepley 
2171f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
217219307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
2173f0cdbbbaSDave May 
2174fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
2175fca3fa51SMatthew G. Knepley     PetscCheck(celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "No active cell DM. DMSWARM_PIC requires you call DMSwarmSetCellDM() or DMSwarmAddCellDM()");
217619307e5cSMatthew G. Knepley     if (celldm->dm->ops->locatepointssubdomain) {
2177f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
2178fca3fa51SMatthew G. Knepley       PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n"));
2179f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
2180f0cdbbbaSDave May     } else {
2181f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
218219307e5cSMatthew G. Knepley       if (celldm->dm->ops->locatepoints) {
2183fca3fa51SMatthew G. Knepley         PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->LocatePoints\n"));
2184fca3fa51SMatthew G. Knepley       } else SETERRQ(PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
2185f0cdbbbaSDave May 
218619307e5cSMatthew G. Knepley       if (celldm->dm->ops->getneighbors) {
2187fca3fa51SMatthew G. Knepley         PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n"));
2188fca3fa51SMatthew G. Knepley       } else SETERRQ(PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
2189f0cdbbbaSDave May 
2190f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
2191f0cdbbbaSDave May     }
2192f0cdbbbaSDave May   }
2193f0cdbbbaSDave May 
2194fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmFinalizeFieldRegister(sw));
2195f0cdbbbaSDave May 
21963454631fSDave May   /* check some fields were registered */
2197fca3fa51SMatthew G. Knepley   PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()");
21983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21993454631fSDave May }
22003454631fSDave May 
220166976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroy_Swarm(DM dm)
2202d71ae5a4SJacob Faibussowitsch {
220357795646SDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
220457795646SDave May 
220557795646SDave May   PetscFunctionBegin;
22063ba16761SJacob Faibussowitsch   if (--swarm->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
220719307e5cSMatthew G. Knepley   PetscCall(PetscObjectListDestroy(&swarm->cellDMs));
220819307e5cSMatthew G. Knepley   PetscCall(PetscFree(swarm->activeCellDM));
22099566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&swarm->db));
22109566063dSJacob Faibussowitsch   PetscCall(PetscFree(swarm));
22113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221257795646SDave May }
221357795646SDave May 
221466976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
2215d71ae5a4SJacob Faibussowitsch {
2216a9ee3421SMatthew G. Knepley   DM            cdm;
221719307e5cSMatthew G. Knepley   DMSwarmCellDM celldm;
2218a9ee3421SMatthew G. Knepley   PetscDraw     draw;
221931403186SMatthew G. Knepley   PetscReal    *coords, oldPause, radius = 0.01;
222019307e5cSMatthew G. Knepley   PetscInt      Np, p, bs, Nfc;
222119307e5cSMatthew G. Knepley   const char  **coordFields;
2222a9ee3421SMatthew G. Knepley 
2223a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
22249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL));
22259566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
22269566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(dm, &cdm));
22279566063dSJacob Faibussowitsch   PetscCall(PetscDrawGetPause(draw, &oldPause));
22289566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, 0.0));
22299566063dSJacob Faibussowitsch   PetscCall(DMView(cdm, viewer));
22309566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetPause(draw, oldPause));
2231a9ee3421SMatthew G. Knepley 
223219307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
223319307e5cSMatthew G. Knepley   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
223419307e5cSMatthew G. Knepley   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);
22359566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(dm, &Np));
223619307e5cSMatthew G. Knepley   PetscCall(DMSwarmGetField(dm, coordFields[0], &bs, NULL, (void **)&coords));
2237a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
2238a9ee3421SMatthew G. Knepley     const PetscInt i = p * bs;
2239a9ee3421SMatthew G. Knepley 
22409566063dSJacob Faibussowitsch     PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE));
2241a9ee3421SMatthew G. Knepley   }
224219307e5cSMatthew G. Knepley   PetscCall(DMSwarmRestoreField(dm, coordFields[0], &bs, NULL, (void **)&coords));
22439566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
22449566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
22459566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
22463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2247a9ee3421SMatthew G. Knepley }
2248a9ee3421SMatthew G. Knepley 
2249d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer)
2250d71ae5a4SJacob Faibussowitsch {
22516a5217c0SMatthew G. Knepley   PetscViewerFormat format;
22526a5217c0SMatthew G. Knepley   PetscInt         *sizes;
22536a5217c0SMatthew G. Knepley   PetscInt          dim, Np, maxSize = 17;
22546a5217c0SMatthew G. Knepley   MPI_Comm          comm;
22556a5217c0SMatthew G. Knepley   PetscMPIInt       rank, size, p;
225619307e5cSMatthew G. Knepley   const char       *name, *cellid;
22576a5217c0SMatthew G. Knepley 
22586a5217c0SMatthew G. Knepley   PetscFunctionBegin;
22596a5217c0SMatthew G. Knepley   PetscCall(PetscViewerGetFormat(viewer, &format));
22606a5217c0SMatthew G. Knepley   PetscCall(DMGetDimension(dm, &dim));
22616a5217c0SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(dm, &Np));
22626a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
22636a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
22646a5217c0SMatthew G. Knepley   PetscCallMPI(MPI_Comm_size(comm, &size));
22656a5217c0SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
226663a3b9bcSJacob Faibussowitsch   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
226763a3b9bcSJacob Faibussowitsch   else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
22686a5217c0SMatthew G. Knepley   if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes));
22696a5217c0SMatthew G. Knepley   else PetscCall(PetscCalloc1(3, &sizes));
22706a5217c0SMatthew G. Knepley   if (size < maxSize) {
22716a5217c0SMatthew G. Knepley     PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
22726a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of particles per rank:"));
22736a5217c0SMatthew G. Knepley     for (p = 0; p < size; ++p) {
22746a5217c0SMatthew G. Knepley       if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]));
22756a5217c0SMatthew G. Knepley     }
22766a5217c0SMatthew G. Knepley   } else {
22776a5217c0SMatthew G. Knepley     PetscInt locMinMax[2] = {Np, Np};
22786a5217c0SMatthew G. Knepley 
22796a5217c0SMatthew G. Knepley     PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
22806a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
22816a5217c0SMatthew G. Knepley   }
22826a5217c0SMatthew G. Knepley   PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
22836a5217c0SMatthew G. Knepley   PetscCall(PetscFree(sizes));
22846a5217c0SMatthew G. Knepley   if (format == PETSC_VIEWER_ASCII_INFO) {
228519307e5cSMatthew G. Knepley     DMSwarmCellDM celldm;
22866a5217c0SMatthew G. Knepley     PetscInt     *cell;
22876a5217c0SMatthew G. Knepley 
22886a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells containing each particle:\n"));
22896a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
229019307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
229119307e5cSMatthew G. Knepley     PetscCall(DMSwarmCellDMGetCellID(celldm, &cellid));
229219307e5cSMatthew G. Knepley     PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&cell));
229363a3b9bcSJacob Faibussowitsch     for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  p%d: %" PetscInt_FMT "\n", p, cell[p]));
22946a5217c0SMatthew G. Knepley     PetscCall(PetscViewerFlush(viewer));
22956a5217c0SMatthew G. Knepley     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
229619307e5cSMatthew G. Knepley     PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&cell));
22976a5217c0SMatthew G. Knepley   }
22983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22996a5217c0SMatthew G. Knepley }
23006a5217c0SMatthew G. Knepley 
230166976f2fSJacob Faibussowitsch static PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
2302d71ae5a4SJacob Faibussowitsch {
23035f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm *)dm->data;
23044fc69c0aSMatthew G. Knepley   PetscBool iascii, ibinary, isvtk, isdraw, ispython;
23055627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
23065627991aSBarry Smith   PetscBool ishdf5;
23075627991aSBarry Smith #endif
23085f50eb2eSDave May 
23095f50eb2eSDave May   PetscFunctionBegin;
23105f50eb2eSDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23115f50eb2eSDave May   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
23139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary));
23149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
23155627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
23169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23175627991aSBarry Smith #endif
23189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
23194fc69c0aSMatthew G. Knepley   PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython));
23205f50eb2eSDave May   if (iascii) {
23216a5217c0SMatthew G. Knepley     PetscViewerFormat format;
23226a5217c0SMatthew G. Knepley 
23236a5217c0SMatthew G. Knepley     PetscCall(PetscViewerGetFormat(viewer, &format));
23246a5217c0SMatthew G. Knepley     switch (format) {
2325d71ae5a4SJacob Faibussowitsch     case PETSC_VIEWER_ASCII_INFO_DETAIL:
2326d71ae5a4SJacob Faibussowitsch       PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT));
2327d71ae5a4SJacob Faibussowitsch       break;
2328d71ae5a4SJacob Faibussowitsch     default:
2329d71ae5a4SJacob Faibussowitsch       PetscCall(DMView_Swarm_Ascii(dm, viewer));
23306a5217c0SMatthew G. Knepley     }
2331f7d195e4SLawrence Mitchell   } else {
23325f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
233348a46eb9SPierre Jolivet     if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer));
23345f50eb2eSDave May #endif
233548a46eb9SPierre Jolivet     if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer));
23364fc69c0aSMatthew G. Knepley     if (ispython) PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)dm));
2337f7d195e4SLawrence Mitchell   }
23383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23395f50eb2eSDave May }
23405f50eb2eSDave May 
2341cc4c1da9SBarry Smith /*@
234220f4b53cSBarry Smith   DMSwarmGetCellSwarm - Extracts a single cell from the `DMSWARM` object, returns it as a single cell `DMSWARM`.
234320f4b53cSBarry 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.
2344d0c080abSJoseph Pusztay 
2345d0c080abSJoseph Pusztay   Noncollective
2346d0c080abSJoseph Pusztay 
234760225df5SJacob Faibussowitsch   Input Parameters:
234820f4b53cSBarry Smith + sw        - the `DMSWARM`
23495627991aSBarry Smith . cellID    - the integer id of the cell to be extracted and filtered
235020f4b53cSBarry Smith - cellswarm - The `DMSWARM` to receive the cell
2351d0c080abSJoseph Pusztay 
2352d0c080abSJoseph Pusztay   Level: beginner
2353d0c080abSJoseph Pusztay 
23545627991aSBarry Smith   Notes:
235520f4b53cSBarry Smith   This presently only supports `DMSWARM_PIC` type
23565627991aSBarry Smith 
235720f4b53cSBarry Smith   Should be restored with `DMSwarmRestoreCellSwarm()`
2358d0c080abSJoseph Pusztay 
235920f4b53cSBarry Smith   Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
236020f4b53cSBarry Smith 
236120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreCellSwarm()`
2362d0c080abSJoseph Pusztay @*/
2363cc4c1da9SBarry Smith PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
2364d71ae5a4SJacob Faibussowitsch {
2365d0c080abSJoseph Pusztay   DM_Swarm   *original = (DM_Swarm *)sw->data;
2366d0c080abSJoseph Pusztay   DMLabel     label;
2367d0c080abSJoseph Pusztay   DM          dmc, subdmc;
2368d0c080abSJoseph Pusztay   PetscInt   *pids, particles, dim;
236919307e5cSMatthew G. Knepley   const char *name;
2370d0c080abSJoseph Pusztay 
2371d0c080abSJoseph Pusztay   PetscFunctionBegin;
2372d0c080abSJoseph Pusztay   /* Configure new swarm */
23739566063dSJacob Faibussowitsch   PetscCall(DMSetType(cellswarm, DMSWARM));
23749566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(sw, &dim));
23759566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(cellswarm, dim));
23769566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC));
2377d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
23789566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db));
23799566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
23809566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles));
23819566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
23829566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db));
23839566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
2384fe11354eSMatthew G. Knepley   PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids));
23859566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(sw, &dmc));
23869566063dSJacob Faibussowitsch   PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label));
23879566063dSJacob Faibussowitsch   PetscCall(DMAddLabel(dmc, label));
23889566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cellID, 1));
238930cbcd5dSksagiyam   PetscCall(DMPlexFilter(dmc, label, 1, PETSC_FALSE, PETSC_FALSE, NULL, &subdmc));
239019307e5cSMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)dmc, &name));
239119307e5cSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)subdmc, name));
23929566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetCellDM(cellswarm, subdmc));
23939566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&label));
23943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2395d0c080abSJoseph Pusztay }
2396d0c080abSJoseph Pusztay 
2397cc4c1da9SBarry Smith /*@
239820f4b53cSBarry Smith   DMSwarmRestoreCellSwarm - Restores a `DMSWARM` object obtained with `DMSwarmGetCellSwarm()`. All fields are copied back into the parent swarm.
2399d0c080abSJoseph Pusztay 
2400d0c080abSJoseph Pusztay   Noncollective
2401d0c080abSJoseph Pusztay 
240260225df5SJacob Faibussowitsch   Input Parameters:
240320f4b53cSBarry Smith + sw        - the parent `DMSWARM`
2404d0c080abSJoseph Pusztay . cellID    - the integer id of the cell to be copied back into the parent swarm
2405d0c080abSJoseph Pusztay - cellswarm - the cell swarm object
2406d0c080abSJoseph Pusztay 
2407d0c080abSJoseph Pusztay   Level: beginner
2408d0c080abSJoseph Pusztay 
24095627991aSBarry Smith   Note:
241020f4b53cSBarry Smith   This only supports `DMSWARM_PIC` types of `DMSWARM`s
2411d0c080abSJoseph Pusztay 
241220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetCellSwarm()`
2413d0c080abSJoseph Pusztay @*/
2414cc4c1da9SBarry Smith PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
2415d71ae5a4SJacob Faibussowitsch {
2416d0c080abSJoseph Pusztay   DM        dmc;
2417d0c080abSJoseph Pusztay   PetscInt *pids, particles, p;
2418d0c080abSJoseph Pusztay 
2419d0c080abSJoseph Pusztay   PetscFunctionBegin;
24209566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetAccess(sw));
24219566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids));
24229566063dSJacob Faibussowitsch   PetscCall(DMSwarmSortRestoreAccess(sw));
2423d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
242448a46eb9SPierre Jolivet   for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p]));
2425d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
24269566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetCellDM(cellswarm, &dmc));
24279566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
2428fe11354eSMatthew G. Knepley   PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids));
24293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2430d0c080abSJoseph Pusztay }
2431d0c080abSJoseph Pusztay 
2432d52c2f21SMatthew G. Knepley /*@
2433d52c2f21SMatthew G. Knepley   DMSwarmComputeMoments - Compute the first three particle moments for a given field
2434d52c2f21SMatthew G. Knepley 
2435d52c2f21SMatthew G. Knepley   Noncollective
2436d52c2f21SMatthew G. Knepley 
2437d52c2f21SMatthew G. Knepley   Input Parameters:
2438d52c2f21SMatthew G. Knepley + sw         - the `DMSWARM`
2439d52c2f21SMatthew G. Knepley . coordinate - the coordinate field name
2440d52c2f21SMatthew G. Knepley - weight     - the weight field name
2441d52c2f21SMatthew G. Knepley 
2442d52c2f21SMatthew G. Knepley   Output Parameter:
2443d52c2f21SMatthew G. Knepley . moments - the field moments
2444d52c2f21SMatthew G. Knepley 
2445d52c2f21SMatthew G. Knepley   Level: intermediate
2446d52c2f21SMatthew G. Knepley 
2447d52c2f21SMatthew G. Knepley   Notes:
2448d52c2f21SMatthew G. Knepley   The `moments` array should be of length bs + 2, where bs is the block size of the coordinate field.
2449d52c2f21SMatthew G. Knepley 
2450d52c2f21SMatthew G. Knepley   The weight field must be a scalar, having blocksize 1.
2451d52c2f21SMatthew G. Knepley 
2452d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMPlexComputeMoments()`
2453d52c2f21SMatthew G. Knepley @*/
2454d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmComputeMoments(DM sw, const char coordinate[], const char weight[], PetscReal moments[])
2455d52c2f21SMatthew G. Knepley {
2456d52c2f21SMatthew G. Knepley   const PetscReal *coords;
2457d52c2f21SMatthew G. Knepley   const PetscReal *w;
2458d52c2f21SMatthew G. Knepley   PetscReal       *mom;
2459d52c2f21SMatthew G. Knepley   PetscDataType    dtc, dtw;
2460d52c2f21SMatthew G. Knepley   PetscInt         bsc, bsw, Np;
2461d52c2f21SMatthew G. Knepley   MPI_Comm         comm;
2462d52c2f21SMatthew G. Knepley 
2463d52c2f21SMatthew G. Knepley   PetscFunctionBegin;
2464d52c2f21SMatthew G. Knepley   PetscValidHeaderSpecific(sw, DM_CLASSID, 1);
2465d52c2f21SMatthew G. Knepley   PetscAssertPointer(coordinate, 2);
2466d52c2f21SMatthew G. Knepley   PetscAssertPointer(weight, 3);
2467d52c2f21SMatthew G. Knepley   PetscAssertPointer(moments, 4);
2468d52c2f21SMatthew G. Knepley   PetscCall(PetscObjectGetComm((PetscObject)sw, &comm));
2469d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, coordinate, &bsc, &dtc, (void **)&coords));
2470d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetField(sw, weight, &bsw, &dtw, (void **)&w));
2471d52c2f21SMatthew G. Knepley   PetscCheck(dtc == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s must be real, not %s", coordinate, PetscDataTypes[dtc]);
2472d52c2f21SMatthew G. Knepley   PetscCheck(dtw == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be real, not %s", weight, PetscDataTypes[dtw]);
2473d52c2f21SMatthew G. Knepley   PetscCheck(bsw == 1, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be a scalar, not blocksize %" PetscInt_FMT, weight, bsw);
2474d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmGetLocalSize(sw, &Np));
2475d52c2f21SMatthew G. Knepley   PetscCall(DMGetWorkArray(sw, bsc + 2, MPIU_REAL, &mom));
2476d52c2f21SMatthew G. Knepley   PetscCall(PetscArrayzero(mom, bsc + 2));
2477d52c2f21SMatthew G. Knepley   for (PetscInt p = 0; p < Np; ++p) {
2478d52c2f21SMatthew G. Knepley     const PetscReal *c  = &coords[p * bsc];
2479d52c2f21SMatthew G. Knepley     const PetscReal  wp = w[p];
2480d52c2f21SMatthew G. Knepley 
2481d52c2f21SMatthew G. Knepley     mom[0] += wp;
2482d52c2f21SMatthew G. Knepley     for (PetscInt d = 0; d < bsc; ++d) {
2483d52c2f21SMatthew G. Knepley       mom[d + 1] += wp * c[d];
2484d52c2f21SMatthew G. Knepley       mom[d + bsc + 1] += wp * PetscSqr(c[d]);
2485d52c2f21SMatthew G. Knepley     }
2486d52c2f21SMatthew G. Knepley   }
2487d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&coords));
2488d52c2f21SMatthew G. Knepley   PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w));
2489d52c2f21SMatthew G. Knepley   PetscCallMPI(MPIU_Allreduce(mom, moments, bsc + 2, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)sw)));
2490d52c2f21SMatthew G. Knepley   PetscCall(DMRestoreWorkArray(sw, bsc + 2, MPIU_REAL, &mom));
2491d0c080abSJoseph Pusztay   PetscFunctionReturn(PETSC_SUCCESS);
2492d0c080abSJoseph Pusztay }
2493d0c080abSJoseph Pusztay 
2494ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Swarm(DM dm, PetscOptionItems PetscOptionsObject)
2495fca3fa51SMatthew G. Knepley {
2496fca3fa51SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2497fca3fa51SMatthew G. Knepley 
2498fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2499fca3fa51SMatthew G. Knepley   PetscOptionsHeadBegin(PetscOptionsObject, "DMSwarm Options");
2500fca3fa51SMatthew G. Knepley   PetscCall(PetscOptionsEnum("-dm_swarm_remap_type", "Remap algorithm", "DMSwarmSetRemapType", DMSwarmRemapTypeNames, (PetscEnum)swarm->remap_type, (PetscEnum *)&swarm->remap_type, NULL));
2501fca3fa51SMatthew G. Knepley   PetscOptionsHeadEnd();
2502fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2503fca3fa51SMatthew G. Knepley }
2504fca3fa51SMatthew G. Knepley 
2505d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
2506d0c080abSJoseph Pusztay 
2507d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Swarm(DM sw)
2508d71ae5a4SJacob Faibussowitsch {
2509d0c080abSJoseph Pusztay   PetscFunctionBegin;
2510d0c080abSJoseph Pusztay   sw->ops->view                     = DMView_Swarm;
2511d0c080abSJoseph Pusztay   sw->ops->load                     = NULL;
2512fca3fa51SMatthew G. Knepley   sw->ops->setfromoptions           = DMSetFromOptions_Swarm;
2513d0c080abSJoseph Pusztay   sw->ops->clone                    = DMClone_Swarm;
2514d0c080abSJoseph Pusztay   sw->ops->setup                    = DMSetup_Swarm;
2515d0c080abSJoseph Pusztay   sw->ops->createlocalsection       = NULL;
2516adc21957SMatthew G. Knepley   sw->ops->createsectionpermutation = NULL;
2517d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints = NULL;
2518d0c080abSJoseph Pusztay   sw->ops->createglobalvector       = DMCreateGlobalVector_Swarm;
2519d0c080abSJoseph Pusztay   sw->ops->createlocalvector        = DMCreateLocalVector_Swarm;
2520d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping  = NULL;
2521d0c080abSJoseph Pusztay   sw->ops->createfieldis            = NULL;
2522d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm       = NULL;
2523d0c080abSJoseph Pusztay   sw->ops->getcoloring              = NULL;
2524d0c080abSJoseph Pusztay   sw->ops->creatematrix             = DMCreateMatrix_Swarm;
2525d0c080abSJoseph Pusztay   sw->ops->createinterpolation      = NULL;
2526d0c080abSJoseph Pusztay   sw->ops->createinjection          = NULL;
2527d0c080abSJoseph Pusztay   sw->ops->createmassmatrix         = DMCreateMassMatrix_Swarm;
2528d0c080abSJoseph Pusztay   sw->ops->refine                   = NULL;
2529d0c080abSJoseph Pusztay   sw->ops->coarsen                  = NULL;
2530d0c080abSJoseph Pusztay   sw->ops->refinehierarchy          = NULL;
2531d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy         = NULL;
2532*9d50c5ebSMatthew G. Knepley   sw->ops->globaltolocalbegin       = DMGlobalToLocalBegin_Swarm;
2533*9d50c5ebSMatthew G. Knepley   sw->ops->globaltolocalend         = DMGlobalToLocalEnd_Swarm;
2534*9d50c5ebSMatthew G. Knepley   sw->ops->localtoglobalbegin       = DMLocalToGlobalBegin_Swarm;
2535*9d50c5ebSMatthew G. Knepley   sw->ops->localtoglobalend         = DMLocalToGlobalEnd_Swarm;
2536d0c080abSJoseph Pusztay   sw->ops->destroy                  = DMDestroy_Swarm;
2537d0c080abSJoseph Pusztay   sw->ops->createsubdm              = NULL;
2538d0c080abSJoseph Pusztay   sw->ops->getdimpoints             = NULL;
2539d0c080abSJoseph Pusztay   sw->ops->locatepoints             = NULL;
2540*9d50c5ebSMatthew G. Knepley   sw->ops->projectfieldlocal        = DMProjectFieldLocal_Swarm;
25413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2542d0c080abSJoseph Pusztay }
2543d0c080abSJoseph Pusztay 
2544d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm)
2545d71ae5a4SJacob Faibussowitsch {
2546d0c080abSJoseph Pusztay   DM_Swarm *swarm = (DM_Swarm *)dm->data;
2547d0c080abSJoseph Pusztay 
2548d0c080abSJoseph Pusztay   PetscFunctionBegin;
2549d0c080abSJoseph Pusztay   swarm->refct++;
2550d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
25519566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM));
25529566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(*newdm));
25532e56dffeSJoe Pusztay   (*newdm)->dim = dm->dim;
25543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2555d0c080abSJoseph Pusztay }
2556d0c080abSJoseph Pusztay 
2557d3a51819SDave May /*MC
25580b4b7b1cSBarry Smith  DMSWARM = "swarm" - A `DM` object for particle methods, such as particle-in-cell (PIC), in which the underlying
25590b4b7b1cSBarry Smith            data is both (i) dynamic in length, (ii) and of arbitrary data type.
2560d3a51819SDave May 
256120f4b53cSBarry Smith  Level: intermediate
256220f4b53cSBarry Smith 
256320f4b53cSBarry Smith  Notes:
25640b4b7b1cSBarry Smith  User data can be represented by `DMSWARM` through a registering "fields" which are to be stored on particles.
256562741f57SDave May  To register a field, the user must provide;
256662741f57SDave May  (a) a unique name;
256762741f57SDave May  (b) the data type (or size in bytes);
256862741f57SDave May  (c) the block size of the data.
2569d3a51819SDave May 
2570d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
2571c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
257220f4b53cSBarry Smith .vb
257320f4b53cSBarry Smith     DMSwarmInitializeFieldRegister(dm)
257420f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
257520f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
257620f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
257720f4b53cSBarry Smith     DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
257820f4b53cSBarry Smith     DMSwarmFinalizeFieldRegister(dm)
257920f4b53cSBarry Smith .ve
2580d3a51819SDave May 
258120f4b53cSBarry Smith  The fields represented by `DMSWARM` are dynamic and can be re-sized at any time.
25820b4b7b1cSBarry Smith  The only restriction imposed by `DMSWARM` is that all fields contain the same number of particles.
2583d3a51819SDave May 
2584d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
25855627991aSBarry Smith  between ranks.
2586d3a51819SDave May 
258720f4b53cSBarry Smith  `DMSWARM` supports the methods `DMCreateGlobalVector()` and `DMCreateLocalVector()`.
258820f4b53cSBarry Smith  As a `DMSWARM` may internally define and store values of different data types,
258920f4b53cSBarry Smith  before calling `DMCreateGlobalVector()` or `DMCreateLocalVector()`, the user must inform `DMSWARM` which
25900b4b7b1cSBarry Smith  fields should be used to define a `Vec` object via `DMSwarmVectorDefineField()`
2591c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
2592c215a47eSMatthew Knepley  compatible with different fields to be created.
2593d3a51819SDave May 
25940b4b7b1cSBarry Smith  A dual representation of fields in the `DMSWARM` and a Vec object is permitted via `DMSwarmCreateGlobalVectorFromField()`
25950b4b7b1cSBarry Smith  Here the data defining the field in the `DMSWARM` is shared with a `Vec`.
2596d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
259720f4b53cSBarry Smith  calls to `DMSwarmCreateGlobalVectorFromField()` and `DMSwarmDestroyGlobalVectorFromField()`.
259820f4b53cSBarry Smith  If the local size of the `DMSWARM` does not match the local size of the global vector
259920f4b53cSBarry Smith  when `DMSwarmDestroyGlobalVectorFromField()` is called, an error is thrown.
2600d3a51819SDave May 
26010b4b7b1cSBarry Smith  Additional high-level support is provided for Particle-In-Cell methods. Refer to `DMSwarmSetType()`.
260262741f57SDave May 
26030b4b7b1cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMType`, `DMCreate()`, `DMSetType()`, `DMSwarmSetType()`, `DMSwarmType`, `DMSwarmCreateGlobalVectorFromField()`,
26040b4b7b1cSBarry Smith          `DMCreateGlobalVector()`, `DMCreateLocalVector()`
2605d3a51819SDave May M*/
2606cc4c1da9SBarry Smith 
2607d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
2608d71ae5a4SJacob Faibussowitsch {
260957795646SDave May   DM_Swarm *swarm;
261057795646SDave May 
261157795646SDave May   PetscFunctionBegin;
261257795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26134dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&swarm));
2614f0cdbbbaSDave May   dm->data = swarm;
26159566063dSJacob Faibussowitsch   PetscCall(DMSwarmDataBucketCreate(&swarm->db));
26169566063dSJacob Faibussowitsch   PetscCall(DMSwarmInitializeFieldRegister(dm));
2617d52c2f21SMatthew G. Knepley   dm->dim                               = 0;
2618d0c080abSJoseph Pusztay   swarm->refct                          = 1;
26193454631fSDave May   swarm->issetup                        = PETSC_FALSE;
2620480eef7bSDave May   swarm->swarm_type                     = DMSWARM_BASIC;
2621480eef7bSDave May   swarm->migrate_type                   = DMSWARM_MIGRATE_BASIC;
2622480eef7bSDave May   swarm->collect_type                   = DMSWARM_COLLECT_BASIC;
262340c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
2624f0cdbbbaSDave May   swarm->collect_view_active            = PETSC_FALSE;
2625f0cdbbbaSDave May   swarm->collect_view_reset_nlocal      = -1;
26269566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Swarm(dm));
26272e956fe4SStefano Zampini   if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId));
26283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
262957795646SDave May }
263019307e5cSMatthew G. Knepley 
263119307e5cSMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
263219307e5cSMatthew G. Knepley    - Share the DM_Swarm structure
263319307e5cSMatthew G. Knepley */
263419307e5cSMatthew G. Knepley PetscErrorCode DMSwarmReplace(DM dm, DM *ndm)
263519307e5cSMatthew G. Knepley {
263619307e5cSMatthew G. Knepley   DM               dmNew = *ndm;
263719307e5cSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
263819307e5cSMatthew G. Knepley   PetscInt         dim;
263919307e5cSMatthew G. Knepley 
264019307e5cSMatthew G. Knepley   PetscFunctionBegin;
264119307e5cSMatthew G. Knepley   if (dm == dmNew) {
264219307e5cSMatthew G. Knepley     PetscCall(DMDestroy(ndm));
264319307e5cSMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
264419307e5cSMatthew G. Knepley   }
264519307e5cSMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
264619307e5cSMatthew G. Knepley   if (!dm->hdr.name) {
264719307e5cSMatthew G. Knepley     const char *name;
264819307e5cSMatthew G. Knepley 
264919307e5cSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)*ndm, &name));
265019307e5cSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
265119307e5cSMatthew G. Knepley   }
265219307e5cSMatthew G. Knepley   PetscCall(DMGetDimension(dmNew, &dim));
265319307e5cSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
265419307e5cSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
265519307e5cSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
265619307e5cSMatthew G. Knepley   PetscCall(DMDestroy_Swarm(dm));
265719307e5cSMatthew G. Knepley   PetscCall(DMInitialize_Swarm(dm));
265819307e5cSMatthew G. Knepley   dm->data = dmNew->data;
265919307e5cSMatthew G. Knepley   ((DM_Swarm *)dmNew->data)->refct++;
266019307e5cSMatthew G. Knepley   PetscCall(DMDestroy(ndm));
266119307e5cSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
266219307e5cSMatthew G. Knepley }
2663fca3fa51SMatthew G. Knepley 
2664fca3fa51SMatthew G. Knepley /*@
2665fca3fa51SMatthew G. Knepley   DMSwarmDuplicate - Creates a new `DMSWARM` with the same fields and cell `DM`s but no particles
2666fca3fa51SMatthew G. Knepley 
2667fca3fa51SMatthew G. Knepley   Collective
2668fca3fa51SMatthew G. Knepley 
2669fca3fa51SMatthew G. Knepley   Input Parameter:
2670fca3fa51SMatthew G. Knepley . sw - the `DMSWARM`
2671fca3fa51SMatthew G. Knepley 
2672fca3fa51SMatthew G. Knepley   Output Parameter:
2673fca3fa51SMatthew G. Knepley . nsw - the new `DMSWARM`
2674fca3fa51SMatthew G. Knepley 
2675fca3fa51SMatthew G. Knepley   Level: beginner
2676fca3fa51SMatthew G. Knepley 
2677fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCreate()`, `DMClone()`
2678fca3fa51SMatthew G. Knepley @*/
2679fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmDuplicate(DM sw, DM *nsw)
2680fca3fa51SMatthew G. Knepley {
2681fca3fa51SMatthew G. Knepley   DM_Swarm         *swarm = (DM_Swarm *)sw->data;
2682fca3fa51SMatthew G. Knepley   DMSwarmDataField *fields;
2683fca3fa51SMatthew G. Knepley   DMSwarmCellDM     celldm, ncelldm;
2684fca3fa51SMatthew G. Knepley   DMSwarmType       stype;
2685fca3fa51SMatthew G. Knepley   const char       *name, **celldmnames;
2686fca3fa51SMatthew G. Knepley   void             *ctx;
2687fca3fa51SMatthew G. Knepley   PetscInt          dim, Nf, Ndm;
2688fca3fa51SMatthew G. Knepley   PetscBool         flg;
2689fca3fa51SMatthew G. Knepley 
2690fca3fa51SMatthew G. Knepley   PetscFunctionBegin;
2691fca3fa51SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), nsw));
2692fca3fa51SMatthew G. Knepley   PetscCall(DMSetType(*nsw, DMSWARM));
2693fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)sw, &name));
2694fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)*nsw, name));
2695fca3fa51SMatthew G. Knepley   PetscCall(DMGetDimension(sw, &dim));
2696fca3fa51SMatthew G. Knepley   PetscCall(DMSetDimension(*nsw, dim));
2697fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetType(sw, &stype));
2698fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmSetType(*nsw, stype));
2699fca3fa51SMatthew G. Knepley   PetscCall(DMGetApplicationContext(sw, &ctx));
2700fca3fa51SMatthew G. Knepley   PetscCall(DMSetApplicationContext(*nsw, ctx));
2701fca3fa51SMatthew G. Knepley 
2702fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmDataBucketGetDMSwarmDataFields(swarm->db, &Nf, &fields));
2703fca3fa51SMatthew G. Knepley   for (PetscInt f = 0; f < Nf; ++f) {
2704fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmDataFieldStringInList(fields[f]->name, ((DM_Swarm *)(*nsw)->data)->db->nfields, (const DMSwarmDataField *)((DM_Swarm *)(*nsw)->data)->db->field, &flg));
2705fca3fa51SMatthew G. Knepley     if (!flg) PetscCall(DMSwarmRegisterPetscDatatypeField(*nsw, fields[f]->name, fields[f]->bs, fields[f]->petsc_type));
2706fca3fa51SMatthew G. Knepley   }
2707fca3fa51SMatthew G. Knepley 
2708fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetCellDMNames(sw, &Ndm, &celldmnames));
2709fca3fa51SMatthew G. Knepley   for (PetscInt c = 0; c < Ndm; ++c) {
2710fca3fa51SMatthew G. Knepley     DM           dm;
2711fca3fa51SMatthew G. Knepley     PetscInt     Ncf;
2712fca3fa51SMatthew G. Knepley     const char **coordfields, **fields;
2713fca3fa51SMatthew G. Knepley 
2714fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmGetCellDMByName(sw, celldmnames[c], &celldm));
2715fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMGetDM(celldm, &dm));
2716fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Ncf, &coordfields));
2717fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMGetFields(celldm, &Nf, &fields));
2718fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMCreate(dm, Nf, fields, Ncf, coordfields, &ncelldm));
2719fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmAddCellDM(*nsw, ncelldm));
2720fca3fa51SMatthew G. Knepley     PetscCall(DMSwarmCellDMDestroy(&ncelldm));
2721fca3fa51SMatthew G. Knepley   }
2722fca3fa51SMatthew G. Knepley   PetscCall(PetscFree(celldmnames));
2723fca3fa51SMatthew G. Knepley 
2724fca3fa51SMatthew G. Knepley   PetscCall(DMSetFromOptions(*nsw));
2725fca3fa51SMatthew G. Knepley   PetscCall(DMSetUp(*nsw));
2726fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmGetCellDMActive(sw, &celldm));
2727fca3fa51SMatthew G. Knepley   PetscCall(PetscObjectGetName((PetscObject)celldm, &name));
2728fca3fa51SMatthew G. Knepley   PetscCall(DMSwarmSetCellDMActive(*nsw, name));
2729fca3fa51SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2730fca3fa51SMatthew G. Knepley }
2731*9d50c5ebSMatthew G. Knepley 
2732*9d50c5ebSMatthew G. Knepley PetscErrorCode DMLocalToGlobalBegin_Swarm(DM dm, Vec l, InsertMode mode, Vec g)
2733*9d50c5ebSMatthew G. Knepley {
2734*9d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
2735*9d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2736*9d50c5ebSMatthew G. Knepley }
2737*9d50c5ebSMatthew G. Knepley 
2738*9d50c5ebSMatthew G. Knepley PetscErrorCode DMLocalToGlobalEnd_Swarm(DM dm, Vec l, InsertMode mode, Vec g)
2739*9d50c5ebSMatthew G. Knepley {
2740*9d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
2741*9d50c5ebSMatthew G. Knepley   switch (mode) {
2742*9d50c5ebSMatthew G. Knepley   case INSERT_VALUES:
2743*9d50c5ebSMatthew G. Knepley     PetscCall(VecCopy(l, g));
2744*9d50c5ebSMatthew G. Knepley     break;
2745*9d50c5ebSMatthew G. Knepley   case ADD_VALUES:
2746*9d50c5ebSMatthew G. Knepley     PetscCall(VecAXPY(g, 1., l));
2747*9d50c5ebSMatthew G. Knepley     break;
2748*9d50c5ebSMatthew G. Knepley   default:
2749*9d50c5ebSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mode not supported: %d", mode);
2750*9d50c5ebSMatthew G. Knepley   }
2751*9d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2752*9d50c5ebSMatthew G. Knepley }
2753*9d50c5ebSMatthew G. Knepley 
2754*9d50c5ebSMatthew G. Knepley PetscErrorCode DMGlobalToLocalBegin_Swarm(DM dm, Vec g, InsertMode mode, Vec l)
2755*9d50c5ebSMatthew G. Knepley {
2756*9d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
2757*9d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2758*9d50c5ebSMatthew G. Knepley }
2759*9d50c5ebSMatthew G. Knepley 
2760*9d50c5ebSMatthew G. Knepley PetscErrorCode DMGlobalToLocalEnd_Swarm(DM dm, Vec g, InsertMode mode, Vec l)
2761*9d50c5ebSMatthew G. Knepley {
2762*9d50c5ebSMatthew G. Knepley   PetscFunctionBegin;
2763*9d50c5ebSMatthew G. Knepley   PetscCall(DMLocalToGlobalEnd_Swarm(dm, g, mode, l));
2764*9d50c5ebSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
2765*9d50c5ebSMatthew G. Knepley }
2766