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