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 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 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 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 @*/ 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 @*/ 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 @*/ 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 */ 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 */ 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 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 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 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 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 */ 466d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *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 */ 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 */ 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 689d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *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 @*/ 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 */ 9421898fd5cSMatthew G. Knepley static PetscErrorCode DMSwarmComputeGradientMatrix_Private(DM sw, DM dm, Mat derv, PetscBool useDeltaFunction, void *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 */ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 @*/ 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 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 @*/ 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 @*/ 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 @*/ 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 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 @*/ 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 @*/ 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 @*/ 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 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 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 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 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 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 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 @*/ 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)); 2573*71f1c950SStefano 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 @*/ 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 @*/ 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 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 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 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 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 */ 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 @*/ 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 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 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 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 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