119307e5cSMatthew G. Knepley #include "petscdmswarm.h" 257795646SDave May #define PETSCDM_DLL 357795646SDave May #include <petsc/private/dmswarmimpl.h> /*I "petscdmswarm.h" I*/ 4e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h> 50643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> 65917a6f0SStefano Zampini #include <petscviewer.h> 75917a6f0SStefano Zampini #include <petscdraw.h> 883c47955SMatthew G. Knepley #include <petscdmplex.h> 94cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h> 10279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h" 11d0c080abSJoseph Pusztay #include <petscdmlabel.h> 12d0c080abSJoseph Pusztay #include <petscsection.h> 1357795646SDave May 14f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort; 15ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd; 16ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack; 17ed923d71SDave May 18ea78f98cSLisandro Dalcin const char *DMSwarmTypeNames[] = {"basic", "pic", NULL}; 19ea78f98cSLisandro Dalcin const char *DMSwarmMigrateTypeNames[] = {"basic", "dmcellnscatter", "dmcellexact", "user", NULL}; 20ea78f98cSLisandro Dalcin const char *DMSwarmCollectTypeNames[] = {"basic", "boundingbox", "general", "user", NULL}; 21fca3fa51SMatthew G. Knepley const char *DMSwarmRemapTypeNames[] = {"none", "pfak", "colella", "DMSwarmRemapType", "DMSWARM_REMAP_", NULL}; 22ea78f98cSLisandro Dalcin const char *DMSwarmPICLayoutTypeNames[] = {"regular", "gauss", "subdivision", NULL}; 23f0cdbbbaSDave May 24f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid"; 25f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank"; 26f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor"; 27f0cdbbbaSDave May 282e956fe4SStefano Zampini PetscInt SwarmDataFieldId = -1; 292e956fe4SStefano Zampini 3074d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 3174d0cae8SMatthew G. Knepley #include <petscviewerhdf5.h> 3274d0cae8SMatthew G. Knepley 3366976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer) 34d71ae5a4SJacob Faibussowitsch { 3574d0cae8SMatthew G. Knepley DM dm; 3674d0cae8SMatthew G. Knepley PetscReal seqval; 3774d0cae8SMatthew G. Knepley PetscInt seqnum, bs; 38eb0c6899SMatthew G. Knepley PetscBool isseq, ists; 3974d0cae8SMatthew G. Knepley 4074d0cae8SMatthew G. Knepley PetscFunctionBegin; 419566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 429566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &bs)); 439566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields")); 449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 459566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval)); 46eb0c6899SMatthew G. Knepley PetscCall(PetscViewerHDF5IsTimestepping(viewer, &ists)); 47eb0c6899SMatthew G. Knepley if (ists) PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); 489566063dSJacob Faibussowitsch /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */ 499566063dSJacob Faibussowitsch PetscCall(VecViewNative(v, viewer)); 509566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs)); 519566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PopGroup(viewer)); 523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5374d0cae8SMatthew G. Knepley } 5474d0cae8SMatthew G. Knepley 5566976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer) 56d71ae5a4SJacob Faibussowitsch { 5719307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 5874d0cae8SMatthew G. Knepley Vec coordinates; 5919307e5cSMatthew G. Knepley PetscInt Np, Nfc; 6074d0cae8SMatthew G. Knepley PetscBool isseq; 6119307e5cSMatthew G. Knepley const char **coordFields; 6274d0cae8SMatthew G. Knepley 6374d0cae8SMatthew G. Knepley PetscFunctionBegin; 6419307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(dm, &celldm)); 6519307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields)); 6619307e5cSMatthew G. Knepley PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc); 679566063dSJacob Faibussowitsch PetscCall(DMSwarmGetSize(dm, &Np)); 6819307e5cSMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(dm, coordFields[0], &coordinates)); 699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 709566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles")); 719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq)); 729566063dSJacob Faibussowitsch PetscCall(VecViewNative(coordinates, viewer)); 739566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np)); 749566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PopGroup(viewer)); 7519307e5cSMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, coordFields[0], &coordinates)); 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7774d0cae8SMatthew G. Knepley } 7874d0cae8SMatthew G. Knepley #endif 7974d0cae8SMatthew G. Knepley 8066976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer) 81d71ae5a4SJacob Faibussowitsch { 8274d0cae8SMatthew G. Knepley DM dm; 83f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5) 8474d0cae8SMatthew G. Knepley PetscBool ishdf5; 85f9558f5cSBarry Smith #endif 8674d0cae8SMatthew G. Knepley 8774d0cae8SMatthew G. Knepley PetscFunctionBegin; 889566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 8928b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 90f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5) 919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 9274d0cae8SMatthew G. Knepley if (ishdf5) { 939566063dSJacob Faibussowitsch PetscCall(VecView_Swarm_HDF5_Internal(v, viewer)); 943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9574d0cae8SMatthew G. Knepley } 96f9558f5cSBarry Smith #endif 979566063dSJacob Faibussowitsch PetscCall(VecViewNative(v, viewer)); 983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9974d0cae8SMatthew G. Knepley } 10074d0cae8SMatthew G. Knepley 101d52c2f21SMatthew G. Knepley /*@C 102d52c2f21SMatthew G. Knepley DMSwarmVectorGetField - Gets the fields from which to define a `Vec` object 1030bf7c1c5SMatthew G. Knepley when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 1040bf7c1c5SMatthew G. Knepley 1050bf7c1c5SMatthew G. Knepley Not collective 1060bf7c1c5SMatthew G. Knepley 1070bf7c1c5SMatthew G. Knepley Input Parameter: 10819307e5cSMatthew G. Knepley . sw - a `DMSWARM` 1090bf7c1c5SMatthew G. Knepley 110d52c2f21SMatthew G. Knepley Output Parameters: 111d52c2f21SMatthew G. Knepley + Nf - the number of fields 112d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field, or NULL if it has not been set 1130bf7c1c5SMatthew G. Knepley 1140bf7c1c5SMatthew G. Knepley Level: beginner 1150bf7c1c5SMatthew G. Knepley 116d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 1170bf7c1c5SMatthew G. Knepley @*/ 11819307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorGetField(DM sw, PetscInt *Nf, const char **fieldnames[]) 1190bf7c1c5SMatthew G. Knepley { 12019307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 12119307e5cSMatthew G. Knepley 1220bf7c1c5SMatthew G. Knepley PetscFunctionBegin; 12319307e5cSMatthew G. Knepley PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM); 12419307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 12519307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetFields(celldm, Nf, fieldnames)); 1260bf7c1c5SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1270bf7c1c5SMatthew G. Knepley } 1280bf7c1c5SMatthew G. Knepley 129cc4c1da9SBarry Smith /*@ 13020f4b53cSBarry Smith DMSwarmVectorDefineField - Sets the field from which to define a `Vec` object 13120f4b53cSBarry Smith when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 13257795646SDave May 13320f4b53cSBarry Smith Collective 13457795646SDave May 13560225df5SJacob Faibussowitsch Input Parameters: 13620f4b53cSBarry Smith + dm - a `DMSWARM` 137d52c2f21SMatthew G. Knepley - fieldname - the textual name given to each registered field 13857795646SDave May 139d3a51819SDave May Level: beginner 14057795646SDave May 141d3a51819SDave May Notes: 14220f4b53cSBarry Smith The field with name `fieldname` must be defined as having a data type of `PetscScalar`. 143e7af74c8SDave May 14420f4b53cSBarry Smith This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`. 14520f4b53cSBarry Smith Multiple calls to `DMSwarmVectorDefineField()` are permitted. 146e7af74c8SDave May 147d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineFields()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 148d3a51819SDave May @*/ 149d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[]) 150d71ae5a4SJacob Faibussowitsch { 151d52c2f21SMatthew G. Knepley PetscFunctionBegin; 152d52c2f21SMatthew G. Knepley PetscCall(DMSwarmVectorDefineFields(dm, 1, &fieldname)); 153d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 154d52c2f21SMatthew G. Knepley } 155d52c2f21SMatthew G. Knepley 156d52c2f21SMatthew G. Knepley /*@C 157d52c2f21SMatthew G. Knepley DMSwarmVectorDefineFields - Sets the fields from which to define a `Vec` object 158d52c2f21SMatthew G. Knepley when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 159d52c2f21SMatthew G. Knepley 160d52c2f21SMatthew G. Knepley Collective, No Fortran support 161d52c2f21SMatthew G. Knepley 162d52c2f21SMatthew G. Knepley Input Parameters: 16319307e5cSMatthew G. Knepley + sw - a `DMSWARM` 164d52c2f21SMatthew G. Knepley . Nf - the number of fields 165d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field 166d52c2f21SMatthew G. Knepley 167d52c2f21SMatthew G. Knepley Level: beginner 168d52c2f21SMatthew G. Knepley 169d52c2f21SMatthew G. Knepley Notes: 170d52c2f21SMatthew G. Knepley Each field with name in `fieldnames` must be defined as having a data type of `PetscScalar`. 171d52c2f21SMatthew G. Knepley 172d52c2f21SMatthew G. Knepley This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`. 173d52c2f21SMatthew G. Knepley Multiple calls to `DMSwarmVectorDefineField()` are permitted. 174d52c2f21SMatthew G. Knepley 175d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 176d52c2f21SMatthew G. Knepley @*/ 17719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineFields(DM sw, PetscInt Nf, const char *fieldnames[]) 178d52c2f21SMatthew G. Knepley { 17919307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 18019307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 181b5bcf523SDave May 182a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 18319307e5cSMatthew G. Knepley PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM); 184d52c2f21SMatthew G. Knepley if (fieldnames) PetscAssertPointer(fieldnames, 3); 18519307e5cSMatthew G. Knepley if (!swarm->issetup) PetscCall(DMSetUp(sw)); 18619307e5cSMatthew G. Knepley PetscCheck(Nf >= 0, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields must be non-negative, not %" PetscInt_FMT, Nf); 18719307e5cSMatthew G. Knepley // Create a dummy cell DM if none has been specified (I think we should not support this mode) 18819307e5cSMatthew G. Knepley if (!swarm->activeCellDM) { 18919307e5cSMatthew G. Knepley DM dm; 19019307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 191b5bcf523SDave May 19219307e5cSMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), &dm)); 19319307e5cSMatthew G. Knepley PetscCall(DMSetType(dm, DMSHELL)); 19419307e5cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, "dummy")); 19519307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 0, NULL, &celldm)); 19619307e5cSMatthew G. Knepley PetscCall(DMDestroy(&dm)); 19719307e5cSMatthew G. Knepley PetscCall(DMSwarmAddCellDM(sw, celldm)); 19819307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm)); 19919307e5cSMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, "dummy")); 20019307e5cSMatthew G. Knepley } 20119307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 20219307e5cSMatthew G. Knepley for (PetscInt f = 0; f < celldm->Nf; ++f) PetscCall(PetscFree(celldm->dmFields[f])); 20319307e5cSMatthew G. Knepley PetscCall(PetscFree(celldm->dmFields)); 20419307e5cSMatthew G. Knepley 20519307e5cSMatthew G. Knepley celldm->Nf = Nf; 20619307e5cSMatthew G. Knepley PetscCall(PetscMalloc1(Nf, &celldm->dmFields)); 207d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 208d52c2f21SMatthew G. Knepley PetscDataType type; 209d52c2f21SMatthew G. Knepley 210d52c2f21SMatthew G. Knepley // Check all fields are of type PETSC_REAL or PETSC_SCALAR 21119307e5cSMatthew G. Knepley PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], NULL, &type)); 21219307e5cSMatthew G. Knepley PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 21319307e5cSMatthew G. Knepley PetscCall(PetscStrallocpy(fieldnames[f], (char **)&celldm->dmFields[f])); 214d52c2f21SMatthew G. Knepley } 2153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 216b5bcf523SDave May } 217b5bcf523SDave May 218cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */ 21919307e5cSMatthew G. Knepley static PetscErrorCode DMCreateGlobalVector_Swarm(DM sw, Vec *vec) 220d71ae5a4SJacob Faibussowitsch { 22119307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 22219307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 223b5bcf523SDave May Vec x; 224b5bcf523SDave May char name[PETSC_MAX_PATH_LEN]; 22519307e5cSMatthew G. Knepley PetscInt bs = 0, n; 226b5bcf523SDave May 227a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 22819307e5cSMatthew G. Knepley if (!swarm->issetup) PetscCall(DMSetUp(sw)); 22919307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 23019307e5cSMatthew G. Knepley PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields"); 23119307e5cSMatthew G. Knepley PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL)); 232cc651181SDave May 233d52c2f21SMatthew G. Knepley PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN)); 23419307e5cSMatthew G. Knepley for (PetscInt f = 0; f < celldm->Nf; ++f) { 23519307e5cSMatthew G. Knepley PetscInt fbs; 236d52c2f21SMatthew G. Knepley PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN)); 23719307e5cSMatthew G. Knepley PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN)); 23819307e5cSMatthew G. Knepley PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL)); 23919307e5cSMatthew G. Knepley bs += fbs; 240d52c2f21SMatthew G. Knepley } 24119307e5cSMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)sw), &x)); 2429566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)x, name)); 24319307e5cSMatthew G. Knepley PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE)); 24419307e5cSMatthew G. Knepley PetscCall(VecSetBlockSize(x, bs)); 24519307e5cSMatthew G. Knepley PetscCall(VecSetDM(x, sw)); 2469566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(x)); 24757d50842SBarry Smith PetscCall(VecSetOperation(x, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Swarm)); 248b5bcf523SDave May *vec = x; 2493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 250b5bcf523SDave May } 251b5bcf523SDave May 252b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */ 25319307e5cSMatthew G. Knepley static PetscErrorCode DMCreateLocalVector_Swarm(DM sw, Vec *vec) 254d71ae5a4SJacob Faibussowitsch { 25519307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 25619307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 257b5bcf523SDave May Vec x; 258b5bcf523SDave May char name[PETSC_MAX_PATH_LEN]; 25919307e5cSMatthew G. Knepley PetscInt bs = 0, n; 260b5bcf523SDave May 261a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 26219307e5cSMatthew G. Knepley if (!swarm->issetup) PetscCall(DMSetUp(sw)); 26319307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 26419307e5cSMatthew G. Knepley PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Active cell DM does not define any fields"); 26519307e5cSMatthew G. Knepley PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL)); 266cc651181SDave May 267d52c2f21SMatthew G. Knepley PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN)); 26819307e5cSMatthew G. Knepley for (PetscInt f = 0; f < celldm->Nf; ++f) { 26919307e5cSMatthew G. Knepley PetscInt fbs; 270d52c2f21SMatthew G. Knepley PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN)); 27119307e5cSMatthew G. Knepley PetscCall(PetscStrlcat(name, celldm->dmFields[f], PETSC_MAX_PATH_LEN)); 27219307e5cSMatthew G. Knepley PetscCall(DMSwarmGetFieldInfo(sw, celldm->dmFields[f], &fbs, NULL)); 27319307e5cSMatthew G. Knepley bs += fbs; 274d52c2f21SMatthew G. Knepley } 2759566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &x)); 2769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)x, name)); 27719307e5cSMatthew G. Knepley PetscCall(VecSetSizes(x, n * bs, PETSC_DETERMINE)); 27819307e5cSMatthew G. Knepley PetscCall(VecSetBlockSize(x, bs)); 27919307e5cSMatthew G. Knepley PetscCall(VecSetDM(x, sw)); 2809566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(x)); 281b5bcf523SDave May *vec = x; 2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 283b5bcf523SDave May } 284b5bcf523SDave May 285d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec) 286d71ae5a4SJacob Faibussowitsch { 287fb1bcc12SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 28877048351SPatrick Sanan DMSwarmDataField gfield; 2892e956fe4SStefano Zampini PetscInt bs, nlocal, fid = -1, cfid = -2; 2902e956fe4SStefano Zampini PetscBool flg; 291d3a51819SDave May 292fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 2932e956fe4SStefano Zampini /* check vector is an inplace array */ 2942e956fe4SStefano Zampini PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid)); 2952e956fe4SStefano Zampini PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg)); 296ea17275aSJose E. Roman (void)flg; /* avoid compiler warning */ 297e978a55eSPierre Jolivet PetscCheck(cfid == fid, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)! %" PetscInt_FMT " != %" PetscInt_FMT, fieldname, cfid, fid); 2989566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(*vec, &nlocal)); 2999566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(*vec, &bs)); 30008401ef6SPierre Jolivet PetscCheck(nlocal / bs == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid"); 3019566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 3029566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldRestoreAccess(gfield)); 3038df78e51SMark Adams PetscCall(VecResetArray(*vec)); 3049566063dSJacob Faibussowitsch PetscCall(VecDestroy(vec)); 3053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 306fb1bcc12SMatthew G. Knepley } 307fb1bcc12SMatthew G. Knepley 308d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec) 309d71ae5a4SJacob Faibussowitsch { 310fb1bcc12SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 311fb1bcc12SMatthew G. Knepley PetscDataType type; 312fb1bcc12SMatthew G. Knepley PetscScalar *array; 3132e956fe4SStefano Zampini PetscInt bs, n, fid; 314fb1bcc12SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 315e4fbd051SBarry Smith PetscMPIInt size; 3167f92dde0SRylanor PetscBool iscuda, iskokkos, iship; 317fb1bcc12SMatthew G. Knepley 318fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 3199566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 3209566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL)); 3219566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array)); 32208401ef6SPierre Jolivet PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 323fb1bcc12SMatthew G. Knepley 3249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 3258df78e51SMark Adams PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos)); 3268df78e51SMark Adams PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda)); 3277f92dde0SRylanor PetscCall(PetscStrcmp(dm->vectype, VECHIP, &iship)); 3288df78e51SMark Adams PetscCall(VecCreate(comm, vec)); 3298df78e51SMark Adams PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE)); 3308df78e51SMark Adams PetscCall(VecSetBlockSize(*vec, bs)); 3318df78e51SMark Adams if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS)); 3328df78e51SMark Adams else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA)); 3337f92dde0SRylanor else if (iship) PetscCall(VecSetType(*vec, VECHIP)); 3348df78e51SMark Adams else PetscCall(VecSetType(*vec, VECSTANDARD)); 3358df78e51SMark Adams PetscCall(VecPlaceArray(*vec, array)); 3368df78e51SMark Adams 3379566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname)); 3389566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*vec, name)); 339fb1bcc12SMatthew G. Knepley 340fb1bcc12SMatthew G. Knepley /* Set guard */ 3412e956fe4SStefano Zampini PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid)); 3422e956fe4SStefano Zampini PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid)); 34374d0cae8SMatthew G. Knepley 3449566063dSJacob Faibussowitsch PetscCall(VecSetDM(*vec, dm)); 34557d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Swarm)); 3463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 347fb1bcc12SMatthew G. Knepley } 348fb1bcc12SMatthew G. Knepley 34919307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], Vec *vec) 35019307e5cSMatthew G. Knepley { 35119307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 35219307e5cSMatthew G. Knepley const PetscScalar *array; 35319307e5cSMatthew G. Knepley PetscInt bs, n, id = 0, cid = -2; 35419307e5cSMatthew G. Knepley PetscBool flg; 35519307e5cSMatthew G. Knepley 35619307e5cSMatthew G. Knepley PetscFunctionBegin; 35719307e5cSMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 35819307e5cSMatthew G. Knepley PetscInt fid; 35919307e5cSMatthew G. Knepley 36019307e5cSMatthew G. Knepley PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid)); 36119307e5cSMatthew G. Knepley id += fid; 36219307e5cSMatthew G. Knepley } 36319307e5cSMatthew G. Knepley PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cid, flg)); 36419307e5cSMatthew G. Knepley (void)flg; /* avoid compiler warning */ 36519307e5cSMatthew G. Knepley PetscCheck(cid == id, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)! %" PetscInt_FMT " != %" PetscInt_FMT, fieldnames[0], cid, id); 36619307e5cSMatthew G. Knepley PetscCall(VecGetLocalSize(*vec, &n)); 36719307e5cSMatthew G. Knepley PetscCall(VecGetBlockSize(*vec, &bs)); 36819307e5cSMatthew G. Knepley n /= bs; 36919307e5cSMatthew G. Knepley PetscCheck(n == swarm->db->L, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid"); 37019307e5cSMatthew G. Knepley PetscCall(VecGetArrayRead(*vec, &array)); 37119307e5cSMatthew G. Knepley for (PetscInt f = 0, off = 0; f < Nf; ++f) { 37219307e5cSMatthew G. Knepley PetscScalar *farray; 37319307e5cSMatthew G. Knepley PetscDataType ftype; 37419307e5cSMatthew G. Knepley PetscInt fbs; 37519307e5cSMatthew G. Knepley 37619307e5cSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray)); 37719307e5cSMatthew G. Knepley PetscCheck(off + fbs <= bs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid blocksize %" PetscInt_FMT " < %" PetscInt_FMT, bs, off + fbs); 37819307e5cSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 37919307e5cSMatthew G. Knepley for (PetscInt b = 0; b < fbs; ++b) farray[i * fbs + b] = array[i * bs + off + b]; 38019307e5cSMatthew G. Knepley } 38119307e5cSMatthew G. Knepley off += fbs; 38219307e5cSMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray)); 38319307e5cSMatthew G. Knepley } 38419307e5cSMatthew G. Knepley PetscCall(VecRestoreArrayRead(*vec, &array)); 38519307e5cSMatthew G. Knepley PetscCall(VecDestroy(vec)); 38619307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 38719307e5cSMatthew G. Knepley } 38819307e5cSMatthew G. Knepley 38919307e5cSMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromFields_Private(DM sw, PetscInt Nf, const char *fieldnames[], MPI_Comm comm, Vec *vec) 39019307e5cSMatthew G. Knepley { 39119307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 39219307e5cSMatthew G. Knepley PetscScalar *array; 39319307e5cSMatthew G. Knepley PetscInt n, bs = 0, id = 0; 39419307e5cSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 39519307e5cSMatthew G. Knepley 39619307e5cSMatthew G. Knepley PetscFunctionBegin; 39719307e5cSMatthew G. Knepley if (!swarm->issetup) PetscCall(DMSetUp(sw)); 39819307e5cSMatthew G. Knepley PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL)); 39919307e5cSMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 40019307e5cSMatthew G. Knepley PetscDataType ftype; 40119307e5cSMatthew G. Knepley PetscInt fbs; 40219307e5cSMatthew G. Knepley 40319307e5cSMatthew G. Knepley PetscCall(DMSwarmGetFieldInfo(sw, fieldnames[f], &fbs, &ftype)); 40419307e5cSMatthew G. Knepley PetscCheck(ftype == PETSC_REAL, PetscObjectComm((PetscObject)sw), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 40519307e5cSMatthew G. Knepley bs += fbs; 40619307e5cSMatthew G. Knepley } 40719307e5cSMatthew G. Knepley 40819307e5cSMatthew G. Knepley PetscCall(VecCreate(comm, vec)); 40919307e5cSMatthew G. Knepley PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE)); 41019307e5cSMatthew G. Knepley PetscCall(VecSetBlockSize(*vec, bs)); 41119307e5cSMatthew G. Knepley PetscCall(VecSetType(*vec, sw->vectype)); 41219307e5cSMatthew G. Knepley 41319307e5cSMatthew G. Knepley PetscCall(VecGetArrayWrite(*vec, &array)); 41419307e5cSMatthew G. Knepley for (PetscInt f = 0, off = 0; f < Nf; ++f) { 41519307e5cSMatthew G. Knepley PetscScalar *farray; 41619307e5cSMatthew G. Knepley PetscDataType ftype; 41719307e5cSMatthew G. Knepley PetscInt fbs; 41819307e5cSMatthew G. Knepley 41919307e5cSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray)); 42019307e5cSMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) { 42119307e5cSMatthew G. Knepley for (PetscInt b = 0; b < fbs; ++b) array[i * bs + off + b] = farray[i * fbs + b]; 42219307e5cSMatthew G. Knepley } 42319307e5cSMatthew G. Knepley off += fbs; 42419307e5cSMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, fieldnames[f], &fbs, &ftype, (void **)&farray)); 42519307e5cSMatthew G. Knepley } 42619307e5cSMatthew G. Knepley PetscCall(VecRestoreArrayWrite(*vec, &array)); 42719307e5cSMatthew G. Knepley 42819307e5cSMatthew G. Knepley PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN)); 42919307e5cSMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 43019307e5cSMatthew G. Knepley PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN)); 43119307e5cSMatthew G. Knepley PetscCall(PetscStrlcat(name, fieldnames[f], PETSC_MAX_PATH_LEN)); 43219307e5cSMatthew G. Knepley } 43319307e5cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*vec, name)); 43419307e5cSMatthew G. Knepley 43519307e5cSMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 43619307e5cSMatthew G. Knepley PetscInt fid; 43719307e5cSMatthew G. Knepley 43819307e5cSMatthew G. Knepley PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldnames[f], &fid)); 43919307e5cSMatthew G. Knepley id += fid; 44019307e5cSMatthew G. Knepley } 44119307e5cSMatthew G. Knepley PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, id)); 44219307e5cSMatthew G. Knepley 44319307e5cSMatthew G. Knepley PetscCall(VecSetDM(*vec, sw)); 44457d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Swarm)); 44519307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 44619307e5cSMatthew G. Knepley } 44719307e5cSMatthew G. Knepley 4480643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by 4490643ed39SMatthew G. Knepley 4500643ed39SMatthew G. Knepley \hat f = \sum_i f_i \phi_i 4510643ed39SMatthew G. Knepley 4520643ed39SMatthew G. Knepley and a particle function is given by 4530643ed39SMatthew G. Knepley 4540643ed39SMatthew G. Knepley f = \sum_i w_i \delta(x - x_i) 4550643ed39SMatthew G. Knepley 4560643ed39SMatthew G. Knepley then we want to require that 4570643ed39SMatthew G. Knepley 4580643ed39SMatthew G. Knepley M \hat f = M_p f 4590643ed39SMatthew G. Knepley 4600643ed39SMatthew G. Knepley where the particle mass matrix is given by 4610643ed39SMatthew G. Knepley 4620643ed39SMatthew G. Knepley (M_p)_{ij} = \int \phi_i \delta(x - x_j) 4630643ed39SMatthew G. Knepley 4640643ed39SMatthew G. Knepley The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in 4650643ed39SMatthew G. Knepley his integral. We allow this with the boolean flag. 4660643ed39SMatthew G. Knepley */ 467d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) 468d71ae5a4SJacob Faibussowitsch { 46983c47955SMatthew G. Knepley const char *name = "Mass Matrix"; 4700643ed39SMatthew G. Knepley MPI_Comm comm; 47119307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 47283c47955SMatthew G. Knepley PetscDS prob; 47383c47955SMatthew G. Knepley PetscSection fsection, globalFSection; 474e8f14785SLisandro Dalcin PetscHSetIJ ht; 4750643ed39SMatthew G. Knepley PetscLayout rLayout, colLayout; 47683c47955SMatthew G. Knepley PetscInt *dnz, *onz; 477adb2528bSMark Adams PetscInt locRows, locCols, rStart, colStart, colEnd, *rowIDXs; 4780643ed39SMatthew G. Knepley PetscReal *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0}; 47983c47955SMatthew G. Knepley PetscScalar *elemMat; 48019307e5cSMatthew G. Knepley PetscInt dim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0, totNc = 0; 48119307e5cSMatthew G. Knepley const char **coordFields; 48219307e5cSMatthew G. Knepley PetscReal **coordVals; 48319307e5cSMatthew G. Knepley PetscInt *bs; 48483c47955SMatthew G. Knepley 48583c47955SMatthew G. Knepley PetscFunctionBegin; 4869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mass, &comm)); 4879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmf, &dim)); 4889566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmf, &prob)); 4899566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 4909566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim)); 4919566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ)); 4929566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection)); 4939566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 4949566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd)); 4959566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mass, &locRows, &locCols)); 49683c47955SMatthew G. Knepley 49719307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(dmc, &celldm)); 49819307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields)); 49919307e5cSMatthew G. Knepley PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs)); 500d52c2f21SMatthew G. Knepley 5019566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &colLayout)); 5029566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(colLayout, locCols)); 5039566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(colLayout, 1)); 5049566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colLayout)); 5059566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd)); 5069566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&colLayout)); 5070643ed39SMatthew G. Knepley 5089566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 5099566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 5109566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 5119566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 5129566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL)); 5139566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 5140643ed39SMatthew G. Knepley 5159566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz)); 5169566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&ht)); 51753e60ab4SJoseph Pusztay 5189566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 51919307e5cSMatthew G. Knepley for (PetscInt field = 0; field < Nf; ++field) { 5200bf7c1c5SMatthew G. Knepley PetscObject obj; 5210bf7c1c5SMatthew G. Knepley PetscClassId id; 5220bf7c1c5SMatthew G. Knepley PetscInt Nc; 5230bf7c1c5SMatthew G. Knepley 5240bf7c1c5SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 5250bf7c1c5SMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 5260bf7c1c5SMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 5270bf7c1c5SMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 5280bf7c1c5SMatthew G. Knepley totNc += Nc; 5290bf7c1c5SMatthew G. Knepley } 5300643ed39SMatthew G. Knepley /* count non-zeros */ 5319566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(dmc)); 53219307e5cSMatthew G. Knepley for (PetscInt field = 0; field < Nf; ++field) { 5330bf7c1c5SMatthew G. Knepley PetscObject obj; 5340bf7c1c5SMatthew G. Knepley PetscClassId id; 5350bf7c1c5SMatthew G. Knepley PetscInt Nc; 5360bf7c1c5SMatthew G. Knepley 5370bf7c1c5SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 5380bf7c1c5SMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 5390bf7c1c5SMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 5400bf7c1c5SMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 5410bf7c1c5SMatthew G. Knepley 54219307e5cSMatthew G. Knepley for (PetscInt cell = cStart; cell < cEnd; ++cell) { 5430643ed39SMatthew G. Knepley PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */ 54483c47955SMatthew G. Knepley PetscInt numFIndices, numCIndices; 54583c47955SMatthew G. Knepley 5469566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 5479566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 548fc7c92abSMatthew G. Knepley maxC = PetscMax(maxC, numCIndices); 54983c47955SMatthew G. Knepley { 550e8f14785SLisandro Dalcin PetscHashIJKey key; 551e8f14785SLisandro Dalcin PetscBool missing; 5520bf7c1c5SMatthew G. Knepley for (PetscInt i = 0; i < numFIndices; ++i) { 553adb2528bSMark Adams key.j = findices[i]; /* global column (from Plex) */ 554adb2528bSMark Adams if (key.j >= 0) { 55583c47955SMatthew G. Knepley /* Get indices for coarse elements */ 5560bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) { 5570bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 5580bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle here 5590bf7c1c5SMatthew G. Knepley key.i = cindices[j] * totNc + c + rStart; /* global cols (from Swarm) */ 560adb2528bSMark Adams if (key.i < 0) continue; 5619566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(ht, key, &missing)); 562966bd95aSPierre Jolivet PetscCheck(missing, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j); 5630643ed39SMatthew G. Knepley if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart]; 564e8f14785SLisandro Dalcin else ++onz[key.i - rStart]; 56583c47955SMatthew G. Knepley } 566fc7c92abSMatthew G. Knepley } 567fc7c92abSMatthew G. Knepley } 5680bf7c1c5SMatthew G. Knepley } 569fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 57083c47955SMatthew G. Knepley } 5719566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 57283c47955SMatthew G. Knepley } 57383c47955SMatthew G. Knepley } 5749566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&ht)); 5759566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL)); 5769566063dSJacob Faibussowitsch PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 5779566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnz, onz)); 5780bf7c1c5SMatthew G. Knepley PetscCall(PetscMalloc3(maxC * totNc * totDim, &elemMat, maxC * totNc, &rowIDXs, maxC * dim, &xi)); 57919307e5cSMatthew G. Knepley for (PetscInt field = 0; field < Nf; ++field) { 580ef0bb6c7SMatthew G. Knepley PetscTabulation Tcoarse; 58183c47955SMatthew G. Knepley PetscObject obj; 582ad9634fcSMatthew G. Knepley PetscClassId id; 58319307e5cSMatthew G. Knepley PetscInt Nc; 58483c47955SMatthew G. Knepley 5859566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 586ad9634fcSMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 587ad9634fcSMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 588ad9634fcSMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 589ea7032a0SMatthew G. Knepley 59019307e5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i])); 59119307e5cSMatthew G. Knepley for (PetscInt cell = cStart; cell < cEnd; ++cell) { 59283c47955SMatthew G. Knepley PetscInt *findices, *cindices; 59383c47955SMatthew G. Knepley PetscInt numFIndices, numCIndices; 59483c47955SMatthew G. Knepley 5950643ed39SMatthew G. Knepley /* TODO: Use DMField instead of assuming affine */ 5969566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ)); 5979566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 5989566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 59919307e5cSMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) { 60019307e5cSMatthew G. Knepley PetscReal xr[8]; 60119307e5cSMatthew G. Knepley PetscInt off = 0; 60219307e5cSMatthew G. Knepley 60319307e5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) { 60419307e5cSMatthew G. Knepley for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[j] * bs[i] + b]; 60519307e5cSMatthew G. Knepley } 60619307e5cSMatthew 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); 60719307e5cSMatthew G. Knepley CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, xr, &xi[j * dim]); 60819307e5cSMatthew G. Knepley } 609ad9634fcSMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse)); 610ad9634fcSMatthew G. Knepley else PetscCall(PetscFVCreateTabulation((PetscFV)obj, 1, numCIndices, xi, 0, &Tcoarse)); 61183c47955SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 6120bf7c1c5SMatthew G. Knepley PetscCall(PetscArrayzero(elemMat, numCIndices * Nc * totDim)); 6130bf7c1c5SMatthew G. Knepley for (PetscInt i = 0; i < numFIndices / Nc; ++i) { 6140bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) { 6150bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 6160bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle and field here 6170643ed39SMatthew G. Knepley /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */ 6180bf7c1c5SMatthew G. Knepley elemMat[(j * totNc + c) * numFIndices + i * Nc + c] += Tcoarse->T[0][(j * numFIndices + i * Nc + c) * Nc + c] * (useDeltaFunction ? 1.0 : detJ); 61983c47955SMatthew G. Knepley } 6200643ed39SMatthew G. Knepley } 6210643ed39SMatthew G. Knepley } 6220bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) 6230bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle here 6240bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) rowIDXs[j * Nc + c] = cindices[j] * totNc + c + rStart; 6250bf7c1c5SMatthew G. Knepley if (0) PetscCall(DMPrintCellMatrix(cell, name, numCIndices * Nc, numFIndices, elemMat)); 6260bf7c1c5SMatthew G. Knepley PetscCall(MatSetValues(mass, numCIndices * Nc, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES)); 627fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 6289566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 6299566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tcoarse)); 63083c47955SMatthew G. Knepley } 63119307e5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i])); 63283c47955SMatthew G. Knepley } 6339566063dSJacob Faibussowitsch PetscCall(PetscFree3(elemMat, rowIDXs, xi)); 6349566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(dmc)); 6359566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ)); 63619307e5cSMatthew G. Knepley PetscCall(PetscFree2(coordVals, bs)); 6379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY)); 6389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY)); 6393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64083c47955SMatthew G. Knepley } 64183c47955SMatthew G. Knepley 642d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */ 643d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m) 644d71ae5a4SJacob Faibussowitsch { 645d0c080abSJoseph Pusztay Vec field; 646d0c080abSJoseph Pusztay PetscInt size; 647d0c080abSJoseph Pusztay 648d0c080abSJoseph Pusztay PetscFunctionBegin; 6499566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(sw, &field)); 6509566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(field, &size)); 6519566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(sw, &field)); 6529566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, m)); 6539566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*m)); 6549566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size)); 6559566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL)); 6569566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*m)); 6579566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY)); 6589566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY)); 6599566063dSJacob Faibussowitsch PetscCall(MatShift(*m, 1.0)); 6609566063dSJacob Faibussowitsch PetscCall(MatSetDM(*m, sw)); 6613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 662d0c080abSJoseph Pusztay } 663d0c080abSJoseph Pusztay 664adb2528bSMark Adams /* FEM cols, Particle rows */ 665d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass) 666d71ae5a4SJacob Faibussowitsch { 66719307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 668895a1698SMatthew G. Knepley PetscSection gsf; 66919307e5cSMatthew G. Knepley PetscInt m, n, Np, bs; 67083c47955SMatthew G. Knepley void *ctx; 67183c47955SMatthew G. Knepley 67283c47955SMatthew G. Knepley PetscFunctionBegin; 67319307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(dmCoarse, &celldm)); 67419307e5cSMatthew G. Knepley PetscCheck(celldm->Nf, PetscObjectComm((PetscObject)dmCoarse), PETSC_ERR_USER, "Active cell DM does not define any fields"); 6759566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 6769566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 6770bf7c1c5SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(dmCoarse, &Np)); 67819307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetBlockSize(celldm, dmCoarse, &bs)); 67919307e5cSMatthew G. Knepley n = Np * bs; 6809566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 6819566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE)); 6829566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 6839566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 68483c47955SMatthew G. Knepley 6859566063dSJacob Faibussowitsch PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx)); 6869566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 6873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68883c47955SMatthew G. Knepley } 68983c47955SMatthew G. Knepley 690d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) 691d71ae5a4SJacob Faibussowitsch { 6924cc7f7b2SMatthew G. Knepley const char *name = "Mass Matrix Square"; 6934cc7f7b2SMatthew G. Knepley MPI_Comm comm; 69419307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 6954cc7f7b2SMatthew G. Knepley PetscDS prob; 6964cc7f7b2SMatthew G. Knepley PetscSection fsection, globalFSection; 6974cc7f7b2SMatthew G. Knepley PetscHSetIJ ht; 6984cc7f7b2SMatthew G. Knepley PetscLayout rLayout, colLayout; 6994cc7f7b2SMatthew G. Knepley PetscInt *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize; 7004cc7f7b2SMatthew G. Knepley PetscInt locRows, locCols, rStart, colStart, colEnd, *rowIDXs; 7014cc7f7b2SMatthew G. Knepley PetscReal *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0}; 7024cc7f7b2SMatthew G. Knepley PetscScalar *elemMat, *elemMatSq; 70319307e5cSMatthew G. Knepley PetscInt cdim, Nf, Nfc, cStart, cEnd, totDim, maxC = 0; 70419307e5cSMatthew G. Knepley const char **coordFields; 70519307e5cSMatthew G. Knepley PetscReal **coordVals; 70619307e5cSMatthew G. Knepley PetscInt *bs; 7074cc7f7b2SMatthew G. Knepley 7084cc7f7b2SMatthew G. Knepley PetscFunctionBegin; 7099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mass, &comm)); 7109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmf, &cdim)); 7119566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmf, &prob)); 7129566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 7139566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim)); 7149566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ)); 7159566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection)); 7169566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 7179566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd)); 7189566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mass, &locRows, &locCols)); 7194cc7f7b2SMatthew G. Knepley 72019307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(dmc, &celldm)); 72119307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields)); 72219307e5cSMatthew G. Knepley PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs)); 723d52c2f21SMatthew G. Knepley 7249566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &colLayout)); 7259566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(colLayout, locCols)); 7269566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(colLayout, 1)); 7279566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colLayout)); 7289566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd)); 7299566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&colLayout)); 7304cc7f7b2SMatthew G. Knepley 7319566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 7329566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 7339566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 7349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 7359566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL)); 7369566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 7374cc7f7b2SMatthew G. Knepley 7389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmf, &depth)); 7399566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize)); 7404cc7f7b2SMatthew G. Knepley maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth); 7419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxAdjSize, &adj)); 7424cc7f7b2SMatthew G. Knepley 7439566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz)); 7449566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&ht)); 7454cc7f7b2SMatthew G. Knepley /* Count nonzeros 7464cc7f7b2SMatthew G. Knepley This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous 7474cc7f7b2SMatthew G. Knepley */ 7489566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(dmc)); 74919307e5cSMatthew G. Knepley for (PetscInt cell = cStart; cell < cEnd; ++cell) { 7504cc7f7b2SMatthew G. Knepley PetscInt *cindices; 7514cc7f7b2SMatthew G. Knepley PetscInt numCIndices; 7524cc7f7b2SMatthew G. Knepley #if 0 7534cc7f7b2SMatthew G. Knepley PetscInt adjSize = maxAdjSize, a, j; 7544cc7f7b2SMatthew G. Knepley #endif 7554cc7f7b2SMatthew G. Knepley 7569566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 7574cc7f7b2SMatthew G. Knepley maxC = PetscMax(maxC, numCIndices); 7584cc7f7b2SMatthew G. Knepley /* Diagonal block */ 75919307e5cSMatthew G. Knepley for (PetscInt i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices; 7604cc7f7b2SMatthew G. Knepley #if 0 7614cc7f7b2SMatthew G. Knepley /* Off-diagonal blocks */ 7629566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj)); 7634cc7f7b2SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 7644cc7f7b2SMatthew G. Knepley if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) { 7654cc7f7b2SMatthew G. Knepley const PetscInt ncell = adj[a]; 7664cc7f7b2SMatthew G. Knepley PetscInt *ncindices; 7674cc7f7b2SMatthew G. Knepley PetscInt numNCIndices; 7684cc7f7b2SMatthew G. Knepley 7699566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices)); 7704cc7f7b2SMatthew G. Knepley { 7714cc7f7b2SMatthew G. Knepley PetscHashIJKey key; 7724cc7f7b2SMatthew G. Knepley PetscBool missing; 7734cc7f7b2SMatthew G. Knepley 7744cc7f7b2SMatthew G. Knepley for (i = 0; i < numCIndices; ++i) { 7754cc7f7b2SMatthew G. Knepley key.i = cindices[i] + rStart; /* global rows (from Swarm) */ 7764cc7f7b2SMatthew G. Knepley if (key.i < 0) continue; 7774cc7f7b2SMatthew G. Knepley for (j = 0; j < numNCIndices; ++j) { 7784cc7f7b2SMatthew G. Knepley key.j = ncindices[j] + rStart; /* global column (from Swarm) */ 7794cc7f7b2SMatthew G. Knepley if (key.j < 0) continue; 7809566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(ht, key, &missing)); 7814cc7f7b2SMatthew G. Knepley if (missing) { 7824cc7f7b2SMatthew G. Knepley if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart]; 7834cc7f7b2SMatthew G. Knepley else ++onz[key.i - rStart]; 7844cc7f7b2SMatthew G. Knepley } 7854cc7f7b2SMatthew G. Knepley } 7864cc7f7b2SMatthew G. Knepley } 7874cc7f7b2SMatthew G. Knepley } 788fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, ncell, &numNCIndices, &ncindices)); 7894cc7f7b2SMatthew G. Knepley } 7904cc7f7b2SMatthew G. Knepley } 7914cc7f7b2SMatthew G. Knepley #endif 792fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 7934cc7f7b2SMatthew G. Knepley } 7949566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&ht)); 7959566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL)); 7969566063dSJacob Faibussowitsch PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 7979566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnz, onz)); 7989566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi)); 7994cc7f7b2SMatthew G. Knepley /* Fill in values 8004cc7f7b2SMatthew G. Knepley Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q) 8014cc7f7b2SMatthew G. Knepley Start just by producing block diagonal 8024cc7f7b2SMatthew G. Knepley Could loop over adjacent cells 8034cc7f7b2SMatthew G. Knepley Produce neighboring element matrix 8044cc7f7b2SMatthew G. Knepley TODO Determine which columns and rows correspond to shared dual vector 8054cc7f7b2SMatthew G. Knepley Do MatMatMult with rectangular matrices 8064cc7f7b2SMatthew G. Knepley Insert block 8074cc7f7b2SMatthew G. Knepley */ 80819307e5cSMatthew G. Knepley for (PetscInt field = 0; field < Nf; ++field) { 8094cc7f7b2SMatthew G. Knepley PetscTabulation Tcoarse; 8104cc7f7b2SMatthew G. Knepley PetscObject obj; 81119307e5cSMatthew G. Knepley PetscInt Nc; 8124cc7f7b2SMatthew G. Knepley 8139566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 8149566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 81563a3b9bcSJacob Faibussowitsch PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc); 81619307e5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i])); 81719307e5cSMatthew G. Knepley for (PetscInt cell = cStart; cell < cEnd; ++cell) { 8184cc7f7b2SMatthew G. Knepley PetscInt *findices, *cindices; 8194cc7f7b2SMatthew G. Knepley PetscInt numFIndices, numCIndices; 8204cc7f7b2SMatthew G. Knepley 8214cc7f7b2SMatthew G. Knepley /* TODO: Use DMField instead of assuming affine */ 8229566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ)); 8239566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 8249566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 82519307e5cSMatthew G. Knepley for (PetscInt p = 0; p < numCIndices; ++p) { 82619307e5cSMatthew G. Knepley PetscReal xr[8]; 82719307e5cSMatthew G. Knepley PetscInt off = 0; 82819307e5cSMatthew G. Knepley 82919307e5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) { 83019307e5cSMatthew G. Knepley for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][cindices[p] * bs[i] + b]; 83119307e5cSMatthew G. Knepley } 83219307e5cSMatthew 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); 83319307e5cSMatthew G. Knepley CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, xr, &xi[p * cdim]); 83419307e5cSMatthew G. Knepley } 8359566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse)); 8364cc7f7b2SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 8379566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, numCIndices * totDim)); 83819307e5cSMatthew G. Knepley for (PetscInt i = 0; i < numFIndices; ++i) { 83919307e5cSMatthew G. Knepley for (PetscInt p = 0; p < numCIndices; ++p) { 84019307e5cSMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 8414cc7f7b2SMatthew G. Knepley /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */ 8424cc7f7b2SMatthew G. Knepley elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ); 8434cc7f7b2SMatthew G. Knepley } 8444cc7f7b2SMatthew G. Knepley } 8454cc7f7b2SMatthew G. Knepley } 8469566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tcoarse)); 84719307e5cSMatthew G. Knepley for (PetscInt p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart; 8489566063dSJacob Faibussowitsch if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat)); 8494cc7f7b2SMatthew G. Knepley /* Block diagonal */ 85078884ca7SMatthew G. Knepley if (numCIndices) { 8514cc7f7b2SMatthew G. Knepley PetscBLASInt blasn, blask; 8524cc7f7b2SMatthew G. Knepley PetscScalar one = 1.0, zero = 0.0; 8534cc7f7b2SMatthew G. Knepley 8549566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(numCIndices, &blasn)); 8559566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(numFIndices, &blask)); 856792fecdfSBarry Smith PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn)); 8574cc7f7b2SMatthew G. Knepley } 8589566063dSJacob Faibussowitsch PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES)); 8594cf0e950SBarry Smith /* TODO off-diagonal */ 860fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 8619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 8624cc7f7b2SMatthew G. Knepley } 86319307e5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(dmc, coordFields[i], &bs[i], NULL, (void **)&coordVals[i])); 8644cc7f7b2SMatthew G. Knepley } 8659566063dSJacob Faibussowitsch PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi)); 8669566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 8679566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(dmc)); 8689566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ)); 86919307e5cSMatthew G. Knepley PetscCall(PetscFree2(coordVals, bs)); 8709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY)); 8719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY)); 8723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8734cc7f7b2SMatthew G. Knepley } 8744cc7f7b2SMatthew G. Knepley 875cc4c1da9SBarry Smith /*@ 8764cc7f7b2SMatthew G. Knepley DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p 8774cc7f7b2SMatthew G. Knepley 87820f4b53cSBarry Smith Collective 8794cc7f7b2SMatthew G. Knepley 88060225df5SJacob Faibussowitsch Input Parameters: 88120f4b53cSBarry Smith + dmCoarse - a `DMSWARM` 88220f4b53cSBarry Smith - dmFine - a `DMPLEX` 8834cc7f7b2SMatthew G. Knepley 88460225df5SJacob Faibussowitsch Output Parameter: 8854cc7f7b2SMatthew G. Knepley . mass - the square of the particle mass matrix 8864cc7f7b2SMatthew G. Knepley 8874cc7f7b2SMatthew G. Knepley Level: advanced 8884cc7f7b2SMatthew G. Knepley 88920f4b53cSBarry Smith Note: 8904cc7f7b2SMatthew G. Knepley We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the 8914cc7f7b2SMatthew G. Knepley future to compute the full normal equations. 8924cc7f7b2SMatthew G. Knepley 89320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMCreateMassMatrix()` 8944cc7f7b2SMatthew G. Knepley @*/ 895d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass) 896d71ae5a4SJacob Faibussowitsch { 8974cc7f7b2SMatthew G. Knepley PetscInt n; 8984cc7f7b2SMatthew G. Knepley void *ctx; 8994cc7f7b2SMatthew G. Knepley 9004cc7f7b2SMatthew G. Knepley PetscFunctionBegin; 9019566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dmCoarse, &n)); 9029566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 9039566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE)); 9049566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 9059566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 9064cc7f7b2SMatthew G. Knepley 9079566063dSJacob Faibussowitsch PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx)); 9089566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view")); 9093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9104cc7f7b2SMatthew G. Knepley } 9114cc7f7b2SMatthew G. Knepley 9121898fd5cSMatthew 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 9131898fd5cSMatthew G. Knepley 9141898fd5cSMatthew G. Knepley \int_X \psi_i \nabla \cdot \hat f = \int_X \psi_i \nabla \cdot f 9151898fd5cSMatthew G. Knepley 9161898fd5cSMatthew G. Knepley and then integrate by parts 9171898fd5cSMatthew G. Knepley 9181898fd5cSMatthew G. Knepley \int_X \nabla \psi_i \cdot \hat f = \int_X \nabla \psi_i \cdot f 9191898fd5cSMatthew G. Knepley 9201898fd5cSMatthew G. Knepley where \psi is from a scalar FE space. If a finite element interpolant is given by 9211898fd5cSMatthew G. Knepley 9221898fd5cSMatthew G. Knepley \hat f^c = \sum_i f_i \phi^c_i 9231898fd5cSMatthew G. Knepley 9241898fd5cSMatthew G. Knepley and a particle function is given by 9251898fd5cSMatthew G. Knepley 9261898fd5cSMatthew G. Knepley f^c = \sum_p f^c_p \delta(x - x_p) 9271898fd5cSMatthew G. Knepley 9281898fd5cSMatthew G. Knepley then we want to require that 9291898fd5cSMatthew G. Knepley 9301898fd5cSMatthew G. Knepley D_f \hat f = D_p f 9311898fd5cSMatthew G. Knepley 9321898fd5cSMatthew G. Knepley where the gradient matrices are given by 9331898fd5cSMatthew G. Knepley 9341898fd5cSMatthew G. Knepley (D_f)_{i(jc)} = \int \partial_c \psi_i \phi_j 9351898fd5cSMatthew G. Knepley (D_p)_{i(jc)} = \int \partial_c \psi_i \delta(x - x_j) 9361898fd5cSMatthew G. Knepley 9371898fd5cSMatthew G. Knepley Thus we need two finite element spaces, a scalar and a vector. The vector space holds the representer for the 9381898fd5cSMatthew 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. 9391898fd5cSMatthew G. Knepley 9401898fd5cSMatthew G. Knepley The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in 9411898fd5cSMatthew G. Knepley his integral. We allow this with the boolean flag. 9421898fd5cSMatthew G. Knepley */ 9431898fd5cSMatthew G. Knepley static PetscErrorCode DMSwarmComputeGradientMatrix_Private(DM sw, DM dm, Mat derv, PetscBool useDeltaFunction, void *ctx) 9441898fd5cSMatthew G. Knepley { 9451898fd5cSMatthew G. Knepley const char *name = "Derivative Matrix"; 9461898fd5cSMatthew G. Knepley MPI_Comm comm; 9471898fd5cSMatthew G. Knepley DMSwarmCellDM celldm; 9481898fd5cSMatthew G. Knepley PetscDS ds; 9491898fd5cSMatthew G. Knepley PetscSection fsection, globalFSection; 9501898fd5cSMatthew G. Knepley PetscLayout rLayout; 9511898fd5cSMatthew G. Knepley PetscInt locRows, rStart, *rowIDXs; 9521898fd5cSMatthew G. Knepley PetscReal *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0}; 9531898fd5cSMatthew G. Knepley PetscScalar *elemMat; 9541898fd5cSMatthew G. Knepley PetscInt cdim, Nf, Nfc, cStart, cEnd, totDim, maxNpc = 0, totNc = 0; 9551898fd5cSMatthew G. Knepley const char **coordFields; 9561898fd5cSMatthew G. Knepley PetscReal **coordVals; 9571898fd5cSMatthew G. Knepley PetscInt *bs; 9581898fd5cSMatthew G. Knepley 9591898fd5cSMatthew G. Knepley PetscFunctionBegin; 9601898fd5cSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)derv, &comm)); 9611898fd5cSMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 9621898fd5cSMatthew G. Knepley PetscCall(DMGetDS(dm, &ds)); 9631898fd5cSMatthew G. Knepley PetscCall(PetscDSGetNumFields(ds, &Nf)); 9641898fd5cSMatthew G. Knepley PetscCheck(Nf == 1, comm, PETSC_ERR_SUP, "Currently, we only support a single field"); 9651898fd5cSMatthew G. Knepley PetscCall(PetscDSGetTotalDimension(ds, &totDim)); 9661898fd5cSMatthew G. Knepley PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ)); 9671898fd5cSMatthew G. Knepley PetscCall(DMGetLocalSection(dm, &fsection)); 9681898fd5cSMatthew G. Knepley PetscCall(DMGetGlobalSection(dm, &globalFSection)); 9691898fd5cSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 9701898fd5cSMatthew G. Knepley PetscCall(MatGetLocalSize(derv, &locRows, NULL)); 9711898fd5cSMatthew G. Knepley 9721898fd5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 9731898fd5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields)); 9741898fd5cSMatthew G. Knepley PetscCheck(Nfc == 1, comm, PETSC_ERR_SUP, "Currently, we only support a single field"); 9751898fd5cSMatthew G. Knepley PetscCall(PetscMalloc2(Nfc, &coordVals, Nfc, &bs)); 9761898fd5cSMatthew G. Knepley 9771898fd5cSMatthew G. Knepley PetscCall(PetscLayoutCreate(comm, &rLayout)); 9781898fd5cSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 9791898fd5cSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(rLayout, cdim)); 9801898fd5cSMatthew G. Knepley PetscCall(PetscLayoutSetUp(rLayout)); 9811898fd5cSMatthew G. Knepley PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL)); 9821898fd5cSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&rLayout)); 9831898fd5cSMatthew G. Knepley 9841898fd5cSMatthew G. Knepley for (PetscInt field = 0; field < Nf; ++field) { 9851898fd5cSMatthew G. Knepley PetscObject obj; 9861898fd5cSMatthew G. Knepley PetscInt Nc; 9871898fd5cSMatthew G. Knepley 9881898fd5cSMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, field, &obj)); 9891898fd5cSMatthew G. Knepley PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 9901898fd5cSMatthew G. Knepley totNc += Nc; 9911898fd5cSMatthew G. Knepley } 9921898fd5cSMatthew G. Knepley PetscCheck(totNc == 1, comm, PETSC_ERR_ARG_WRONG, "The number of field components %" PetscInt_FMT " != 1", totNc); 9931898fd5cSMatthew G. Knepley /* count non-zeros */ 9941898fd5cSMatthew G. Knepley PetscCall(DMSwarmSortGetAccess(sw)); 9951898fd5cSMatthew G. Knepley for (PetscInt field = 0; field < Nf; ++field) { 9961898fd5cSMatthew G. Knepley PetscObject obj; 9971898fd5cSMatthew G. Knepley PetscInt Nc; 9981898fd5cSMatthew G. Knepley 9991898fd5cSMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, field, &obj)); 10001898fd5cSMatthew G. Knepley PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 10011898fd5cSMatthew G. Knepley for (PetscInt cell = cStart; cell < cEnd; ++cell) { 10021898fd5cSMatthew G. Knepley PetscInt *pind; 10031898fd5cSMatthew G. Knepley PetscInt Npc; 10041898fd5cSMatthew G. Knepley 10051898fd5cSMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, cell, &Npc, &pind)); 10061898fd5cSMatthew G. Knepley maxNpc = PetscMax(maxNpc, Npc); 10071898fd5cSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, cell, &Npc, &pind)); 10081898fd5cSMatthew G. Knepley } 10091898fd5cSMatthew G. Knepley } 10101898fd5cSMatthew G. Knepley PetscCall(PetscMalloc3(maxNpc * cdim * totDim, &elemMat, maxNpc * cdim, &rowIDXs, maxNpc * cdim, &xi)); 10111898fd5cSMatthew G. Knepley for (PetscInt field = 0; field < Nf; ++field) { 10121898fd5cSMatthew G. Knepley PetscTabulation Tcoarse; 10131898fd5cSMatthew G. Knepley PetscFE fe; 10141898fd5cSMatthew G. Knepley 10151898fd5cSMatthew G. Knepley PetscCall(PetscDSGetDiscretization(ds, field, (PetscObject *)&fe)); 10161898fd5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmGetField(sw, coordFields[i], &bs[i], NULL, (void **)&coordVals[i])); 10171898fd5cSMatthew G. Knepley for (PetscInt cell = cStart; cell < cEnd; ++cell) { 10181898fd5cSMatthew G. Knepley PetscInt *findices, *pind; 10191898fd5cSMatthew G. Knepley PetscInt numFIndices, Npc; 10201898fd5cSMatthew G. Knepley 10211898fd5cSMatthew G. Knepley /* TODO: Use DMField instead of assuming affine */ 10221898fd5cSMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, invJ, &detJ)); 10231898fd5cSMatthew G. Knepley PetscCall(DMPlexGetClosureIndices(dm, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 10241898fd5cSMatthew G. Knepley PetscCall(DMSwarmSortGetPointsPerCell(sw, cell, &Npc, &pind)); 10251898fd5cSMatthew G. Knepley for (PetscInt j = 0; j < Npc; ++j) { 10261898fd5cSMatthew G. Knepley PetscReal xr[8]; 10271898fd5cSMatthew G. Knepley PetscInt off = 0; 10281898fd5cSMatthew G. Knepley 10291898fd5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) { 10301898fd5cSMatthew G. Knepley for (PetscInt b = 0; b < bs[i]; ++b, ++off) xr[off] = coordVals[i][pind[j] * bs[i] + b]; 10311898fd5cSMatthew G. Knepley } 10321898fd5cSMatthew 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); 10331898fd5cSMatthew G. Knepley CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, xr, &xi[j * cdim]); 10341898fd5cSMatthew G. Knepley } 10351898fd5cSMatthew G. Knepley PetscCall(PetscFECreateTabulation(fe, 1, Npc, xi, 1, &Tcoarse)); 10361898fd5cSMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 10371898fd5cSMatthew G. Knepley PetscCall(PetscArrayzero(elemMat, Npc * cdim * totDim)); 10381898fd5cSMatthew G. Knepley for (PetscInt i = 0; i < numFIndices; ++i) { 10391898fd5cSMatthew G. Knepley for (PetscInt j = 0; j < Npc; ++j) { 1040*8c5add6aSPierre Jolivet /* D[((p*pdim + i)*Nc + c)*cdim + d] is the value at point p for basis function i, component c, derivative d */ 10411898fd5cSMatthew G. Knepley for (PetscInt d = 0; d < cdim; ++d) { 10421898fd5cSMatthew G. Knepley xi[d] = 0.; 10431898fd5cSMatthew G. Knepley for (PetscInt e = 0; e < cdim; ++e) xi[d] += invJ[e * cdim + d] * Tcoarse->T[1][(j * numFIndices + i) * cdim + e]; 10441898fd5cSMatthew G. Knepley elemMat[(j * cdim + d) * numFIndices + i] += xi[d] * (useDeltaFunction ? 1.0 : detJ); 10451898fd5cSMatthew G. Knepley } 10461898fd5cSMatthew G. Knepley } 10471898fd5cSMatthew G. Knepley } 10481898fd5cSMatthew G. Knepley for (PetscInt j = 0; j < Npc; ++j) 10491898fd5cSMatthew G. Knepley for (PetscInt d = 0; d < cdim; ++d) rowIDXs[j * cdim + d] = pind[j] * cdim + d + rStart; 10501898fd5cSMatthew G. Knepley if (0) PetscCall(DMPrintCellMatrix(cell, name, Npc * cdim, numFIndices, elemMat)); 10511898fd5cSMatthew G. Knepley PetscCall(MatSetValues(derv, Npc * cdim, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES)); 10521898fd5cSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, cell, &Npc, &pind)); 10531898fd5cSMatthew G. Knepley PetscCall(DMPlexRestoreClosureIndices(dm, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 10541898fd5cSMatthew G. Knepley PetscCall(PetscTabulationDestroy(&Tcoarse)); 10551898fd5cSMatthew G. Knepley } 10561898fd5cSMatthew G. Knepley for (PetscInt i = 0; i < Nfc; ++i) PetscCall(DMSwarmRestoreField(sw, coordFields[i], &bs[i], NULL, (void **)&coordVals[i])); 10571898fd5cSMatthew G. Knepley } 10581898fd5cSMatthew G. Knepley PetscCall(PetscFree3(elemMat, rowIDXs, xi)); 10591898fd5cSMatthew G. Knepley PetscCall(DMSwarmSortRestoreAccess(sw)); 10601898fd5cSMatthew G. Knepley PetscCall(PetscFree3(v0, J, invJ)); 10611898fd5cSMatthew G. Knepley PetscCall(PetscFree2(coordVals, bs)); 10621898fd5cSMatthew G. Knepley PetscCall(MatAssemblyBegin(derv, MAT_FINAL_ASSEMBLY)); 10631898fd5cSMatthew G. Knepley PetscCall(MatAssemblyEnd(derv, MAT_FINAL_ASSEMBLY)); 10641898fd5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 10651898fd5cSMatthew G. Knepley } 10661898fd5cSMatthew G. Knepley 10671898fd5cSMatthew G. Knepley /* FEM cols: this is a scalar space 10681898fd5cSMatthew G. Knepley Particle rows: this is a vector space that contracts with the derivative 10691898fd5cSMatthew G. Knepley */ 10701898fd5cSMatthew G. Knepley static PetscErrorCode DMCreateGradientMatrix_Swarm(DM sw, DM dm, Mat *derv) 10711898fd5cSMatthew G. Knepley { 10721898fd5cSMatthew G. Knepley DMSwarmCellDM celldm; 10731898fd5cSMatthew G. Knepley PetscSection gs; 10741898fd5cSMatthew G. Knepley PetscInt cdim, m, n, Np, bs; 10751898fd5cSMatthew G. Knepley void *ctx; 10761898fd5cSMatthew G. Knepley MPI_Comm comm; 10771898fd5cSMatthew G. Knepley 10781898fd5cSMatthew G. Knepley PetscFunctionBegin; 10791898fd5cSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm)); 10801898fd5cSMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 10811898fd5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 10821898fd5cSMatthew G. Knepley PetscCheck(celldm->Nf, comm, PETSC_ERR_USER, "Active cell DM does not define any fields"); 10831898fd5cSMatthew G. Knepley PetscCall(DMGetGlobalSection(dm, &gs)); 10841898fd5cSMatthew G. Knepley PetscCall(PetscSectionGetConstrainedStorageSize(gs, &n)); 10851898fd5cSMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 10861898fd5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetBlockSize(celldm, sw, &bs)); 10871898fd5cSMatthew G. Knepley PetscCheck(cdim == bs, comm, PETSC_ERR_ARG_WRONG, "Coordinate dimension %" PetscInt_FMT " != %" PetscInt_FMT " swarm field block size", cdim, bs); 10881898fd5cSMatthew G. Knepley m = Np * bs; 10891898fd5cSMatthew G. Knepley PetscCall(MatCreate(PetscObjectComm((PetscObject)sw), derv)); 10901898fd5cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*derv, "Swarm Derivative Matrix")); 10911898fd5cSMatthew G. Knepley PetscCall(MatSetSizes(*derv, m, n, PETSC_DETERMINE, PETSC_DETERMINE)); 10921898fd5cSMatthew G. Knepley PetscCall(MatSetType(*derv, sw->mattype)); 10931898fd5cSMatthew G. Knepley PetscCall(DMGetApplicationContext(dm, &ctx)); 10941898fd5cSMatthew G. Knepley 10951898fd5cSMatthew G. Knepley PetscCall(DMSwarmComputeGradientMatrix_Private(sw, dm, *derv, PETSC_TRUE, ctx)); 10961898fd5cSMatthew G. Knepley PetscCall(MatViewFromOptions(*derv, NULL, "-gradient_mat_view")); 10971898fd5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 10981898fd5cSMatthew G. Knepley } 10991898fd5cSMatthew G. Knepley 1100cc4c1da9SBarry Smith /*@ 110120f4b53cSBarry Smith DMSwarmCreateGlobalVectorFromField - Creates a `Vec` object sharing the array associated with a given field 1102d3a51819SDave May 110320f4b53cSBarry Smith Collective 1104d3a51819SDave May 110560225df5SJacob Faibussowitsch Input Parameters: 110620f4b53cSBarry Smith + dm - a `DMSWARM` 110762741f57SDave May - fieldname - the textual name given to a registered field 1108d3a51819SDave May 110960225df5SJacob Faibussowitsch Output Parameter: 1110d3a51819SDave May . vec - the vector 1111d3a51819SDave May 1112d3a51819SDave May Level: beginner 1113d3a51819SDave May 1114cc4c1da9SBarry Smith Note: 111520f4b53cSBarry Smith The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromField()`. 11168b8a3813SDave May 111720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()` 1118d3a51819SDave May @*/ 1119d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) 1120d71ae5a4SJacob Faibussowitsch { 1121fb1bcc12SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 1122b5bcf523SDave May 1123fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 1124ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 11259566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec)); 11263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1127b5bcf523SDave May } 1128b5bcf523SDave May 1129cc4c1da9SBarry Smith /*@ 113020f4b53cSBarry Smith DMSwarmDestroyGlobalVectorFromField - Destroys the `Vec` object which share the array associated with a given field 1131d3a51819SDave May 113220f4b53cSBarry Smith Collective 1133d3a51819SDave May 113460225df5SJacob Faibussowitsch Input Parameters: 113520f4b53cSBarry Smith + dm - a `DMSWARM` 113662741f57SDave May - fieldname - the textual name given to a registered field 1137d3a51819SDave May 113860225df5SJacob Faibussowitsch Output Parameter: 1139d3a51819SDave May . vec - the vector 1140d3a51819SDave May 1141d3a51819SDave May Level: beginner 1142d3a51819SDave May 114320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()` 1144d3a51819SDave May @*/ 1145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) 1146d71ae5a4SJacob Faibussowitsch { 1147fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 1148ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 11499566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec)); 11503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1151b5bcf523SDave May } 1152b5bcf523SDave May 1153cc4c1da9SBarry Smith /*@ 115420f4b53cSBarry Smith DMSwarmCreateLocalVectorFromField - Creates a `Vec` object sharing the array associated with a given field 1155fb1bcc12SMatthew G. Knepley 115620f4b53cSBarry Smith Collective 1157fb1bcc12SMatthew G. Knepley 115860225df5SJacob Faibussowitsch Input Parameters: 115920f4b53cSBarry Smith + dm - a `DMSWARM` 116062741f57SDave May - fieldname - the textual name given to a registered field 1161fb1bcc12SMatthew G. Knepley 116260225df5SJacob Faibussowitsch Output Parameter: 1163fb1bcc12SMatthew G. Knepley . vec - the vector 1164fb1bcc12SMatthew G. Knepley 1165fb1bcc12SMatthew G. Knepley Level: beginner 1166fb1bcc12SMatthew G. Knepley 116720f4b53cSBarry Smith Note: 11688b8a3813SDave May The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField(). 11698b8a3813SDave May 117020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()` 1171fb1bcc12SMatthew G. Knepley @*/ 1172d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) 1173d71ae5a4SJacob Faibussowitsch { 1174fb1bcc12SMatthew G. Knepley MPI_Comm comm = PETSC_COMM_SELF; 1175bbe8250bSMatthew G. Knepley 1176fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 11779566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec)); 11783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1179bbe8250bSMatthew G. Knepley } 1180fb1bcc12SMatthew G. Knepley 1181cc4c1da9SBarry Smith /*@ 118220f4b53cSBarry Smith DMSwarmDestroyLocalVectorFromField - Destroys the `Vec` object which share the array associated with a given field 1183fb1bcc12SMatthew G. Knepley 118420f4b53cSBarry Smith Collective 1185fb1bcc12SMatthew G. Knepley 118660225df5SJacob Faibussowitsch Input Parameters: 118720f4b53cSBarry Smith + dm - a `DMSWARM` 118862741f57SDave May - fieldname - the textual name given to a registered field 1189fb1bcc12SMatthew G. Knepley 119060225df5SJacob Faibussowitsch Output Parameter: 1191fb1bcc12SMatthew G. Knepley . vec - the vector 1192fb1bcc12SMatthew G. Knepley 1193fb1bcc12SMatthew G. Knepley Level: beginner 1194fb1bcc12SMatthew G. Knepley 119520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()` 1196fb1bcc12SMatthew G. Knepley @*/ 1197d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) 1198d71ae5a4SJacob Faibussowitsch { 1199fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 1200ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 12019566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec)); 12023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1203bbe8250bSMatthew G. Knepley } 1204bbe8250bSMatthew G. Knepley 1205cc4c1da9SBarry Smith /*@ 120619307e5cSMatthew G. Knepley DMSwarmCreateGlobalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set 120719307e5cSMatthew G. Knepley 120819307e5cSMatthew G. Knepley Collective 120919307e5cSMatthew G. Knepley 121019307e5cSMatthew G. Knepley Input Parameters: 121119307e5cSMatthew G. Knepley + dm - a `DMSWARM` 121219307e5cSMatthew G. Knepley . Nf - the number of fields 121319307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields 121419307e5cSMatthew G. Knepley 121519307e5cSMatthew G. Knepley Output Parameter: 121619307e5cSMatthew G. Knepley . vec - the vector 121719307e5cSMatthew G. Knepley 121819307e5cSMatthew G. Knepley Level: beginner 121919307e5cSMatthew G. Knepley 122019307e5cSMatthew G. Knepley Notes: 122119307e5cSMatthew G. Knepley The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromFields()`. 122219307e5cSMatthew G. Knepley 122319307e5cSMatthew G. Knepley This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateGlobalVectorFromField()` 122419307e5cSMatthew G. Knepley 122519307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromFields()` 122619307e5cSMatthew G. Knepley @*/ 122719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec) 122819307e5cSMatthew G. Knepley { 122919307e5cSMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 123019307e5cSMatthew G. Knepley 123119307e5cSMatthew G. Knepley PetscFunctionBegin; 123219307e5cSMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 123319307e5cSMatthew G. Knepley PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec)); 123419307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 123519307e5cSMatthew G. Knepley } 123619307e5cSMatthew G. Knepley 123719307e5cSMatthew G. Knepley /*@ 123819307e5cSMatthew G. Knepley DMSwarmDestroyGlobalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set 123919307e5cSMatthew G. Knepley 124019307e5cSMatthew G. Knepley Collective 124119307e5cSMatthew G. Knepley 124219307e5cSMatthew G. Knepley Input Parameters: 124319307e5cSMatthew G. Knepley + dm - a `DMSWARM` 124419307e5cSMatthew G. Knepley . Nf - the number of fields 124519307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields 124619307e5cSMatthew G. Knepley 124719307e5cSMatthew G. Knepley Output Parameter: 124819307e5cSMatthew G. Knepley . vec - the vector 124919307e5cSMatthew G. Knepley 125019307e5cSMatthew G. Knepley Level: beginner 125119307e5cSMatthew G. Knepley 125219307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()` 125319307e5cSMatthew G. Knepley @*/ 125419307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyGlobalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec) 125519307e5cSMatthew G. Knepley { 125619307e5cSMatthew G. Knepley PetscFunctionBegin; 125719307e5cSMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 125819307e5cSMatthew G. Knepley PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec)); 125919307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 126019307e5cSMatthew G. Knepley } 126119307e5cSMatthew G. Knepley 126219307e5cSMatthew G. Knepley /*@ 126319307e5cSMatthew G. Knepley DMSwarmCreateLocalVectorFromFields - Creates a `Vec` object sharing the array associated with a given field set 126419307e5cSMatthew G. Knepley 126519307e5cSMatthew G. Knepley Collective 126619307e5cSMatthew G. Knepley 126719307e5cSMatthew G. Knepley Input Parameters: 126819307e5cSMatthew G. Knepley + dm - a `DMSWARM` 126919307e5cSMatthew G. Knepley . Nf - the number of fields 127019307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields 127119307e5cSMatthew G. Knepley 127219307e5cSMatthew G. Knepley Output Parameter: 127319307e5cSMatthew G. Knepley . vec - the vector 127419307e5cSMatthew G. Knepley 127519307e5cSMatthew G. Knepley Level: beginner 127619307e5cSMatthew G. Knepley 127719307e5cSMatthew G. Knepley Notes: 127819307e5cSMatthew G. Knepley The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField(). 127919307e5cSMatthew G. Knepley 128019307e5cSMatthew G. Knepley This vector is copyin-copyout, rather than a direct pointer like `DMSwarmCreateLocalVectorFromField()` 128119307e5cSMatthew G. Knepley 128219307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()` 128319307e5cSMatthew G. Knepley @*/ 128419307e5cSMatthew G. Knepley PetscErrorCode DMSwarmCreateLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec) 128519307e5cSMatthew G. Knepley { 128619307e5cSMatthew G. Knepley MPI_Comm comm = PETSC_COMM_SELF; 128719307e5cSMatthew G. Knepley 128819307e5cSMatthew G. Knepley PetscFunctionBegin; 128919307e5cSMatthew G. Knepley PetscCall(DMSwarmCreateVectorFromFields_Private(dm, Nf, fieldnames, comm, vec)); 129019307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 129119307e5cSMatthew G. Knepley } 129219307e5cSMatthew G. Knepley 129319307e5cSMatthew G. Knepley /*@ 129419307e5cSMatthew G. Knepley DMSwarmDestroyLocalVectorFromFields - Destroys the `Vec` object which share the array associated with a given field set 129519307e5cSMatthew G. Knepley 129619307e5cSMatthew G. Knepley Collective 129719307e5cSMatthew G. Knepley 129819307e5cSMatthew G. Knepley Input Parameters: 129919307e5cSMatthew G. Knepley + dm - a `DMSWARM` 130019307e5cSMatthew G. Knepley . Nf - the number of fields 130119307e5cSMatthew G. Knepley - fieldnames - the textual names given to the registered fields 130219307e5cSMatthew G. Knepley 130319307e5cSMatthew G. Knepley Output Parameter: 130419307e5cSMatthew G. Knepley . vec - the vector 130519307e5cSMatthew G. Knepley 130619307e5cSMatthew G. Knepley Level: beginner 130719307e5cSMatthew G. Knepley 130819307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromFields()` 130919307e5cSMatthew G. Knepley @*/ 131019307e5cSMatthew G. Knepley PetscErrorCode DMSwarmDestroyLocalVectorFromFields(DM dm, PetscInt Nf, const char *fieldnames[], Vec *vec) 131119307e5cSMatthew G. Knepley { 131219307e5cSMatthew G. Knepley PetscFunctionBegin; 131319307e5cSMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 131419307e5cSMatthew G. Knepley PetscCall(DMSwarmDestroyVectorFromFields_Private(dm, Nf, fieldnames, vec)); 131519307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 131619307e5cSMatthew G. Knepley } 131719307e5cSMatthew G. Knepley 131819307e5cSMatthew G. Knepley /*@ 131920f4b53cSBarry Smith DMSwarmInitializeFieldRegister - Initiates the registration of fields to a `DMSWARM` 1320d3a51819SDave May 132120f4b53cSBarry Smith Collective 1322d3a51819SDave May 132360225df5SJacob Faibussowitsch Input Parameter: 132420f4b53cSBarry Smith . dm - a `DMSWARM` 1325d3a51819SDave May 1326d3a51819SDave May Level: beginner 1327d3a51819SDave May 132820f4b53cSBarry Smith Note: 132920f4b53cSBarry Smith After all fields have been registered, you must call `DMSwarmFinalizeFieldRegister()`. 1330d3a51819SDave May 133120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`, 1332db781477SPatrick Sanan `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 1333d3a51819SDave May @*/ 1334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeFieldRegister(DM dm) 1335d71ae5a4SJacob Faibussowitsch { 13365f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 13373454631fSDave May 1338521f74f9SMatthew G. Knepley PetscFunctionBegin; 1339cc651181SDave May if (!swarm->field_registration_initialized) { 13405f50eb2eSDave May swarm->field_registration_initialized = PETSC_TRUE; 1341da81f932SPierre Jolivet PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifier */ 13429566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT)); /* used for communication */ 1343cc651181SDave May } 13443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13455f50eb2eSDave May } 13465f50eb2eSDave May 134774d0cae8SMatthew G. Knepley /*@ 134820f4b53cSBarry Smith DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a `DMSWARM` 1349d3a51819SDave May 135020f4b53cSBarry Smith Collective 1351d3a51819SDave May 135260225df5SJacob Faibussowitsch Input Parameter: 135320f4b53cSBarry Smith . dm - a `DMSWARM` 1354d3a51819SDave May 1355d3a51819SDave May Level: beginner 1356d3a51819SDave May 135720f4b53cSBarry Smith Note: 135820f4b53cSBarry Smith After `DMSwarmFinalizeFieldRegister()` has been called, no new fields can be defined on the `DMSWARM`. 1359d3a51819SDave May 136020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`, 1361db781477SPatrick Sanan `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 1362d3a51819SDave May @*/ 1363d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm) 1364d71ae5a4SJacob Faibussowitsch { 13655f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 13666845f8f5SDave May 1367521f74f9SMatthew G. Knepley PetscFunctionBegin; 136848a46eb9SPierre Jolivet if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db)); 1369f0cdbbbaSDave May swarm->field_registration_finalized = PETSC_TRUE; 13703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13715f50eb2eSDave May } 13725f50eb2eSDave May 137374d0cae8SMatthew G. Knepley /*@ 137420f4b53cSBarry Smith DMSwarmSetLocalSizes - Sets the length of all registered fields on the `DMSWARM` 1375d3a51819SDave May 137620f4b53cSBarry Smith Not Collective 1377d3a51819SDave May 137860225df5SJacob Faibussowitsch Input Parameters: 1379fca3fa51SMatthew G. Knepley + sw - a `DMSWARM` 1380d3a51819SDave May . nlocal - the length of each registered field 138162741f57SDave May - buffer - the length of the buffer used to efficient dynamic re-sizing 1382d3a51819SDave May 1383d3a51819SDave May Level: beginner 1384d3a51819SDave May 138520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()` 1386d3a51819SDave May @*/ 1387fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmSetLocalSizes(DM sw, PetscInt nlocal, PetscInt buffer) 1388d71ae5a4SJacob Faibussowitsch { 1389fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1390fca3fa51SMatthew G. Knepley PetscMPIInt rank; 1391fca3fa51SMatthew G. Knepley PetscInt *rankval; 13925f50eb2eSDave May 1393521f74f9SMatthew G. Knepley PetscFunctionBegin; 13949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0)); 13959566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer)); 13969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0)); 1397fca3fa51SMatthew G. Knepley 1398fca3fa51SMatthew G. Knepley // Initialize values in pid and rank placeholders 1399fca3fa51SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sw), &rank)); 1400fca3fa51SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmField_rank, NULL, NULL, (void **)&rankval)); 1401fca3fa51SMatthew G. Knepley for (PetscInt p = 0; p < nlocal; p++) rankval[p] = rank; 1402fca3fa51SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, DMSwarmField_rank, NULL, NULL, (void **)&rankval)); 1403fca3fa51SMatthew G. Knepley /* TODO: [pid - use MPI_Scan] */ 14043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14055f50eb2eSDave May } 14065f50eb2eSDave May 140774d0cae8SMatthew G. Knepley /*@ 140820f4b53cSBarry Smith DMSwarmSetCellDM - Attaches a `DM` to a `DMSWARM` 1409d3a51819SDave May 141020f4b53cSBarry Smith Collective 1411d3a51819SDave May 141260225df5SJacob Faibussowitsch Input Parameters: 141319307e5cSMatthew G. Knepley + sw - a `DMSWARM` 141419307e5cSMatthew G. Knepley - dm - the `DM` to attach to the `DMSWARM` 1415d3a51819SDave May 1416d3a51819SDave May Level: beginner 1417d3a51819SDave May 141820f4b53cSBarry Smith Note: 141919307e5cSMatthew G. Knepley The attached `DM` (dm) will be queried for point location and 142020f4b53cSBarry Smith neighbor MPI-rank information if `DMSwarmMigrate()` is called. 1421d3a51819SDave May 142220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()` 1423d3a51819SDave May @*/ 142419307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM sw, DM dm) 1425d71ae5a4SJacob Faibussowitsch { 142619307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 142719307e5cSMatthew G. Knepley const char *name; 142819307e5cSMatthew G. Knepley char *coordName; 1429d52c2f21SMatthew G. Knepley 1430d52c2f21SMatthew G. Knepley PetscFunctionBegin; 1431d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 143219307e5cSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 143319307e5cSMatthew G. Knepley PetscCall(PetscStrallocpy(DMSwarmPICField_coor, &coordName)); 143419307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(dm, 0, NULL, 1, (const char **)&coordName, &celldm)); 143519307e5cSMatthew G. Knepley PetscCall(PetscFree(coordName)); 143619307e5cSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)celldm, &name)); 143719307e5cSMatthew G. Knepley PetscCall(DMSwarmAddCellDM(sw, celldm)); 143819307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm)); 143919307e5cSMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, name)); 1440d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1441d52c2f21SMatthew G. Knepley } 1442d52c2f21SMatthew G. Knepley 1443d52c2f21SMatthew G. Knepley /*@ 144419307e5cSMatthew G. Knepley DMSwarmGetCellDM - Fetches the active cell `DM` 1445d52c2f21SMatthew G. Knepley 1446d52c2f21SMatthew G. Knepley Collective 1447d52c2f21SMatthew G. Knepley 1448d52c2f21SMatthew G. Knepley Input Parameter: 1449d52c2f21SMatthew G. Knepley . sw - a `DMSWARM` 1450d52c2f21SMatthew G. Knepley 145119307e5cSMatthew G. Knepley Output Parameter: 145219307e5cSMatthew G. Knepley . dm - the active `DM` for the `DMSWARM` 145319307e5cSMatthew G. Knepley 1454d52c2f21SMatthew G. Knepley Level: beginner 1455d52c2f21SMatthew G. Knepley 145619307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()` 1457d52c2f21SMatthew G. Knepley @*/ 145819307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM sw, DM *dm) 1459d52c2f21SMatthew G. Knepley { 1460d52c2f21SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 146119307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 146219307e5cSMatthew G. Knepley 146319307e5cSMatthew G. Knepley PetscFunctionBegin; 1464fca3fa51SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 146519307e5cSMatthew G. Knepley PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)&celldm)); 146619307e5cSMatthew G. Knepley PetscCheck(celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "There is no cell DM named %s in this Swarm", swarm->activeCellDM); 146719307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, dm)); 146819307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 146919307e5cSMatthew G. Knepley } 147019307e5cSMatthew G. Knepley 1471fca3fa51SMatthew G. Knepley /*@C 1472fca3fa51SMatthew G. Knepley DMSwarmGetCellDMNames - Get the list of cell `DM` names 1473fca3fa51SMatthew G. Knepley 1474fca3fa51SMatthew G. Knepley Not collective 1475fca3fa51SMatthew G. Knepley 1476fca3fa51SMatthew G. Knepley Input Parameter: 1477fca3fa51SMatthew G. Knepley . sw - a `DMSWARM` 1478fca3fa51SMatthew G. Knepley 1479fca3fa51SMatthew G. Knepley Output Parameters: 1480fca3fa51SMatthew G. Knepley + Ndm - the number of `DMSwarmCellDM` in the `DMSWARM` 1481fca3fa51SMatthew G. Knepley - celldms - the name of each `DMSwarmCellDM` 1482fca3fa51SMatthew G. Knepley 1483fca3fa51SMatthew G. Knepley Level: beginner 1484fca3fa51SMatthew G. Knepley 1485fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmGetCellDMByName()` 1486fca3fa51SMatthew G. Knepley @*/ 1487fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMNames(DM sw, PetscInt *Ndm, const char **celldms[]) 1488fca3fa51SMatthew G. Knepley { 1489fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1490fca3fa51SMatthew G. Knepley PetscObjectList next = swarm->cellDMs; 1491fca3fa51SMatthew G. Knepley PetscInt n = 0; 1492fca3fa51SMatthew G. Knepley 1493fca3fa51SMatthew G. Knepley PetscFunctionBegin; 1494fca3fa51SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 1495fca3fa51SMatthew G. Knepley PetscAssertPointer(Ndm, 2); 1496fca3fa51SMatthew G. Knepley PetscAssertPointer(celldms, 3); 1497fca3fa51SMatthew G. Knepley while (next) { 1498fca3fa51SMatthew G. Knepley next = next->next; 1499fca3fa51SMatthew G. Knepley ++n; 1500fca3fa51SMatthew G. Knepley } 1501fca3fa51SMatthew G. Knepley PetscCall(PetscMalloc1(n, celldms)); 1502fca3fa51SMatthew G. Knepley next = swarm->cellDMs; 1503fca3fa51SMatthew G. Knepley n = 0; 1504fca3fa51SMatthew G. Knepley while (next) { 1505fca3fa51SMatthew G. Knepley (*celldms)[n] = (const char *)next->obj->name; 1506fca3fa51SMatthew G. Knepley next = next->next; 1507fca3fa51SMatthew G. Knepley ++n; 1508fca3fa51SMatthew G. Knepley } 1509fca3fa51SMatthew G. Knepley *Ndm = n; 1510fca3fa51SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1511fca3fa51SMatthew G. Knepley } 1512fca3fa51SMatthew G. Knepley 151319307e5cSMatthew G. Knepley /*@ 151419307e5cSMatthew G. Knepley DMSwarmSetCellDMActive - Activates a cell `DM` for a `DMSWARM` 151519307e5cSMatthew G. Knepley 151619307e5cSMatthew G. Knepley Collective 151719307e5cSMatthew G. Knepley 151819307e5cSMatthew G. Knepley Input Parameters: 151919307e5cSMatthew G. Knepley + sw - a `DMSWARM` 152019307e5cSMatthew G. Knepley - name - name of the cell `DM` to active for the `DMSWARM` 152119307e5cSMatthew G. Knepley 152219307e5cSMatthew G. Knepley Level: beginner 152319307e5cSMatthew G. Knepley 152419307e5cSMatthew G. Knepley Note: 152519307e5cSMatthew G. Knepley The attached `DM` (dmcell) will be queried for point location and 152619307e5cSMatthew G. Knepley neighbor MPI-rank information if `DMSwarmMigrate()` is called. 152719307e5cSMatthew G. Knepley 152819307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()` 152919307e5cSMatthew G. Knepley @*/ 153019307e5cSMatthew G. Knepley PetscErrorCode DMSwarmSetCellDMActive(DM sw, const char name[]) 153119307e5cSMatthew G. Knepley { 153219307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 153319307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 1534d52c2f21SMatthew G. Knepley 1535d52c2f21SMatthew G. Knepley PetscFunctionBegin; 1536d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 153719307e5cSMatthew G. Knepley PetscCall(PetscInfo(sw, "Setting cell DM to %s\n", name)); 153819307e5cSMatthew G. Knepley PetscCall(PetscFree(swarm->activeCellDM)); 153919307e5cSMatthew G. Knepley PetscCall(PetscStrallocpy(name, (char **)&swarm->activeCellDM)); 154019307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 154119307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1542d52c2f21SMatthew G. Knepley } 154319307e5cSMatthew G. Knepley 154419307e5cSMatthew G. Knepley /*@ 154519307e5cSMatthew G. Knepley DMSwarmGetCellDMActive - Returns the active cell `DM` for a `DMSWARM` 154619307e5cSMatthew G. Knepley 154719307e5cSMatthew G. Knepley Collective 154819307e5cSMatthew G. Knepley 154919307e5cSMatthew G. Knepley Input Parameter: 155019307e5cSMatthew G. Knepley . sw - a `DMSWARM` 155119307e5cSMatthew G. Knepley 155219307e5cSMatthew G. Knepley Output Parameter: 155319307e5cSMatthew G. Knepley . celldm - the active `DMSwarmCellDM` 155419307e5cSMatthew G. Knepley 155519307e5cSMatthew G. Knepley Level: beginner 155619307e5cSMatthew G. Knepley 155719307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCellDM`, `DMSwarmSetType()`, `DMSwarmAddCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()` 155819307e5cSMatthew G. Knepley @*/ 155919307e5cSMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMActive(DM sw, DMSwarmCellDM *celldm) 156019307e5cSMatthew G. Knepley { 156119307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 156219307e5cSMatthew G. Knepley 156319307e5cSMatthew G. Knepley PetscFunctionBegin; 156419307e5cSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 1565fca3fa51SMatthew G. Knepley PetscAssertPointer(celldm, 2); 156619307e5cSMatthew G. Knepley PetscCheck(swarm->activeCellDM, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no active cell DM"); 156719307e5cSMatthew G. Knepley PetscCall(PetscObjectListFind(swarm->cellDMs, swarm->activeCellDM, (PetscObject *)celldm)); 1568fca3fa51SMatthew G. Knepley PetscCheck(*celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no valid cell DM for %s", swarm->activeCellDM); 1569fca3fa51SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1570fca3fa51SMatthew G. Knepley } 1571fca3fa51SMatthew G. Knepley 1572fca3fa51SMatthew G. Knepley /*@C 1573fca3fa51SMatthew G. Knepley DMSwarmGetCellDMByName - Get a `DMSwarmCellDM` from its name 1574fca3fa51SMatthew G. Knepley 1575fca3fa51SMatthew G. Knepley Not collective 1576fca3fa51SMatthew G. Knepley 1577fca3fa51SMatthew G. Knepley Input Parameters: 1578fca3fa51SMatthew G. Knepley + sw - a `DMSWARM` 1579fca3fa51SMatthew G. Knepley - name - the name 1580fca3fa51SMatthew G. Knepley 1581fca3fa51SMatthew G. Knepley Output Parameter: 1582fca3fa51SMatthew G. Knepley . celldm - the `DMSwarmCellDM` 1583fca3fa51SMatthew G. Knepley 1584fca3fa51SMatthew G. Knepley Level: beginner 1585fca3fa51SMatthew G. Knepley 1586fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmGetCellDMNames()` 1587fca3fa51SMatthew G. Knepley @*/ 1588fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDMByName(DM sw, const char name[], DMSwarmCellDM *celldm) 1589fca3fa51SMatthew G. Knepley { 1590fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1591fca3fa51SMatthew G. Knepley 1592fca3fa51SMatthew G. Knepley PetscFunctionBegin; 1593fca3fa51SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 1594fca3fa51SMatthew G. Knepley PetscAssertPointer(name, 2); 1595fca3fa51SMatthew G. Knepley PetscAssertPointer(celldm, 3); 1596fca3fa51SMatthew G. Knepley PetscCall(PetscObjectListFind(swarm->cellDMs, name, (PetscObject *)celldm)); 1597fca3fa51SMatthew G. Knepley PetscCheck(*celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONGSTATE, "Swarm has no valid cell DM for %s", name); 159819307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 159919307e5cSMatthew G. Knepley } 160019307e5cSMatthew G. Knepley 160119307e5cSMatthew G. Knepley /*@ 160219307e5cSMatthew G. Knepley DMSwarmAddCellDM - Adds a cell `DM` to the `DMSWARM` 160319307e5cSMatthew G. Knepley 160419307e5cSMatthew G. Knepley Collective 160519307e5cSMatthew G. Knepley 160619307e5cSMatthew G. Knepley Input Parameters: 160719307e5cSMatthew G. Knepley + sw - a `DMSWARM` 160819307e5cSMatthew G. Knepley - celldm - the `DMSwarmCellDM` 160919307e5cSMatthew G. Knepley 161019307e5cSMatthew G. Knepley Level: beginner 161119307e5cSMatthew G. Knepley 161219307e5cSMatthew G. Knepley Note: 161319307e5cSMatthew G. Knepley Cell DMs with the same name will share the cellid field 161419307e5cSMatthew G. Knepley 161519307e5cSMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmPushCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()` 161619307e5cSMatthew G. Knepley @*/ 161719307e5cSMatthew G. Knepley PetscErrorCode DMSwarmAddCellDM(DM sw, DMSwarmCellDM celldm) 161819307e5cSMatthew G. Knepley { 161919307e5cSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 162019307e5cSMatthew G. Knepley const char *name; 162119307e5cSMatthew G. Knepley PetscInt dim; 162219307e5cSMatthew G. Knepley PetscBool flg; 162319307e5cSMatthew G. Knepley MPI_Comm comm; 162419307e5cSMatthew G. Knepley 162519307e5cSMatthew G. Knepley PetscFunctionBegin; 162619307e5cSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 162719307e5cSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm)); 162819307e5cSMatthew G. Knepley PetscValidHeaderSpecific(celldm, DMSWARMCELLDM_CLASSID, 2); 162919307e5cSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)celldm, &name)); 163019307e5cSMatthew G. Knepley PetscCall(PetscObjectListAdd(&swarm->cellDMs, name, (PetscObject)celldm)); 163119307e5cSMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 163219307e5cSMatthew G. Knepley for (PetscInt f = 0; f < celldm->Nfc; ++f) { 163319307e5cSMatthew G. Knepley PetscCall(DMSwarmDataFieldStringInList(celldm->coordFields[f], swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg)); 163419307e5cSMatthew G. Knepley if (!flg) { 163519307e5cSMatthew G. Knepley PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->coordFields[f], dim, PETSC_DOUBLE)); 163619307e5cSMatthew G. Knepley } else { 163719307e5cSMatthew G. Knepley PetscDataType dt; 163819307e5cSMatthew G. Knepley PetscInt bs; 163919307e5cSMatthew G. Knepley 164019307e5cSMatthew G. Knepley PetscCall(DMSwarmGetFieldInfo(sw, celldm->coordFields[f], &bs, &dt)); 164119307e5cSMatthew 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); 164219307e5cSMatthew G. Knepley PetscCheck(dt == PETSC_DOUBLE, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s has datatype %s != PETSC_DOUBLE", celldm->coordFields[f], PetscDataTypes[dt]); 164319307e5cSMatthew G. Knepley } 164419307e5cSMatthew G. Knepley } 164519307e5cSMatthew G. Knepley // Assume that DMs with the same name share the cellid field 164619307e5cSMatthew G. Knepley PetscCall(DMSwarmDataFieldStringInList(celldm->cellid, swarm->db->nfields, (const DMSwarmDataField *)swarm->db->field, &flg)); 164719307e5cSMatthew G. Knepley if (!flg) { 164819307e5cSMatthew G. Knepley PetscBool isShell, isDummy; 164919307e5cSMatthew G. Knepley const char *name; 165019307e5cSMatthew G. Knepley 165119307e5cSMatthew G. Knepley // Allow dummy DMSHELL (I don't think we should support this mode) 165219307e5cSMatthew G. Knepley PetscCall(PetscObjectTypeCompare((PetscObject)celldm->dm, DMSHELL, &isShell)); 165319307e5cSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)celldm->dm, &name)); 165419307e5cSMatthew G. Knepley PetscCall(PetscStrcmp(name, "dummy", &isDummy)); 165519307e5cSMatthew G. Knepley if (!isShell || !isDummy) PetscCall(DMSwarmRegisterPetscDatatypeField(sw, celldm->cellid, 1, PETSC_INT)); 165619307e5cSMatthew G. Knepley } 165719307e5cSMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(sw, name)); 16583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1659fe39f135SDave May } 1660fe39f135SDave May 166174d0cae8SMatthew G. Knepley /*@ 1662d5b43468SJose E. Roman DMSwarmGetLocalSize - Retrieves the local length of fields registered 1663d3a51819SDave May 166420f4b53cSBarry Smith Not Collective 1665d3a51819SDave May 166660225df5SJacob Faibussowitsch Input Parameter: 166720f4b53cSBarry Smith . dm - a `DMSWARM` 1668d3a51819SDave May 166960225df5SJacob Faibussowitsch Output Parameter: 1670d3a51819SDave May . nlocal - the length of each registered field 1671d3a51819SDave May 1672d3a51819SDave May Level: beginner 1673d3a51819SDave May 167420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()` 1675d3a51819SDave May @*/ 1676d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal) 1677d71ae5a4SJacob Faibussowitsch { 1678dcf43ee8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1679dcf43ee8SDave May 1680521f74f9SMatthew G. Knepley PetscFunctionBegin; 16819566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL)); 16823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1683dcf43ee8SDave May } 1684dcf43ee8SDave May 168574d0cae8SMatthew G. Knepley /*@ 1686d5b43468SJose E. Roman DMSwarmGetSize - Retrieves the total length of fields registered 1687d3a51819SDave May 168820f4b53cSBarry Smith Collective 1689d3a51819SDave May 169060225df5SJacob Faibussowitsch Input Parameter: 169120f4b53cSBarry Smith . dm - a `DMSWARM` 1692d3a51819SDave May 169360225df5SJacob Faibussowitsch Output Parameter: 1694d3a51819SDave May . n - the total length of each registered field 1695d3a51819SDave May 1696d3a51819SDave May Level: beginner 1697d3a51819SDave May 1698d3a51819SDave May Note: 169920f4b53cSBarry Smith This calls `MPI_Allreduce()` upon each call (inefficient but safe) 1700d3a51819SDave May 170120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()` 1702d3a51819SDave May @*/ 1703d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n) 1704d71ae5a4SJacob Faibussowitsch { 1705dcf43ee8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 17065627991aSBarry Smith PetscInt nlocal; 1707dcf43ee8SDave May 1708521f74f9SMatthew G. Knepley PetscFunctionBegin; 17099566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL)); 1710462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 17113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1712dcf43ee8SDave May } 1713dcf43ee8SDave May 1714ce78bad3SBarry Smith /*@C 171520f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField - Register a field to a `DMSWARM` with a native PETSc data type 1716d3a51819SDave May 171720f4b53cSBarry Smith Collective 1718d3a51819SDave May 171960225df5SJacob Faibussowitsch Input Parameters: 172020f4b53cSBarry Smith + dm - a `DMSWARM` 1721d3a51819SDave May . fieldname - the textual name to identify this field 1722d3a51819SDave May . blocksize - the number of each data type 172320f4b53cSBarry Smith - type - a valid PETSc data type (`PETSC_CHAR`, `PETSC_SHORT`, `PETSC_INT`, `PETSC_FLOAT`, `PETSC_REAL`, `PETSC_LONG`) 1724d3a51819SDave May 1725d3a51819SDave May Level: beginner 1726d3a51819SDave May 1727d3a51819SDave May Notes: 17288b8a3813SDave May The textual name for each registered field must be unique. 1729d3a51819SDave May 173020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 1731d3a51819SDave May @*/ 1732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type) 1733d71ae5a4SJacob Faibussowitsch { 1734b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1735b62e03f8SDave May size_t size; 1736b62e03f8SDave May 1737521f74f9SMatthew G. Knepley PetscFunctionBegin; 173828b400f6SJacob Faibussowitsch PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first"); 173928b400f6SJacob Faibussowitsch PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first"); 17405f50eb2eSDave May 174108401ef6SPierre Jolivet PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 174208401ef6SPierre Jolivet PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 174308401ef6SPierre Jolivet PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 174408401ef6SPierre Jolivet PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 174508401ef6SPierre Jolivet PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 1746b62e03f8SDave May 17479566063dSJacob Faibussowitsch PetscCall(PetscDataTypeGetSize(type, &size)); 1748b62e03f8SDave May /* Load a specific data type into data bucket, specifying textual name and its size in bytes */ 17499566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL)); 175052c3ed93SDave May { 175177048351SPatrick Sanan DMSwarmDataField gfield; 175252c3ed93SDave May 17539566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 17549566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize)); 175552c3ed93SDave May } 1756b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = type; 17573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1758b62e03f8SDave May } 1759b62e03f8SDave May 1760d3a51819SDave May /*@C 176120f4b53cSBarry Smith DMSwarmRegisterUserStructField - Register a user defined struct to a `DMSWARM` 1762d3a51819SDave May 176320f4b53cSBarry Smith Collective 1764d3a51819SDave May 176560225df5SJacob Faibussowitsch Input Parameters: 176620f4b53cSBarry Smith + dm - a `DMSWARM` 1767d3a51819SDave May . fieldname - the textual name to identify this field 176862741f57SDave May - size - the size in bytes of the user struct of each data type 1769d3a51819SDave May 1770d3a51819SDave May Level: beginner 1771d3a51819SDave May 177220f4b53cSBarry Smith Note: 17738b8a3813SDave May The textual name for each registered field must be unique. 1774d3a51819SDave May 177520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()` 1776d3a51819SDave May @*/ 1777d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size) 1778d71ae5a4SJacob Faibussowitsch { 1779b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1780b62e03f8SDave May 1781521f74f9SMatthew G. Knepley PetscFunctionBegin; 17829566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL)); 1783b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT; 17843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1785b62e03f8SDave May } 1786b62e03f8SDave May 1787d3a51819SDave May /*@C 178820f4b53cSBarry Smith DMSwarmRegisterUserDatatypeField - Register a user defined data type to a `DMSWARM` 1789d3a51819SDave May 179020f4b53cSBarry Smith Collective 1791d3a51819SDave May 179260225df5SJacob Faibussowitsch Input Parameters: 179320f4b53cSBarry Smith + dm - a `DMSWARM` 1794d3a51819SDave May . fieldname - the textual name to identify this field 1795d3a51819SDave May . size - the size in bytes of the user data type 179662741f57SDave May - blocksize - the number of each data type 1797d3a51819SDave May 1798d3a51819SDave May Level: beginner 1799d3a51819SDave May 180020f4b53cSBarry Smith Note: 18018b8a3813SDave May The textual name for each registered field must be unique. 1802d3a51819SDave May 180342747ad1SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()` 1804d3a51819SDave May @*/ 1805d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize) 1806d71ae5a4SJacob Faibussowitsch { 1807b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1808b62e03f8SDave May 1809521f74f9SMatthew G. Knepley PetscFunctionBegin; 18109566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL)); 1811320740a0SDave May { 181277048351SPatrick Sanan DMSwarmDataField gfield; 1813320740a0SDave May 18149566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 18159566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize)); 1816320740a0SDave May } 1817b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN; 18183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1819b62e03f8SDave May } 1820b62e03f8SDave May 1821d3a51819SDave May /*@C 1822d3a51819SDave May DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field 1823d3a51819SDave May 1824cc4c1da9SBarry Smith Not Collective, No Fortran Support 1825d3a51819SDave May 182660225df5SJacob Faibussowitsch Input Parameters: 182720f4b53cSBarry Smith + dm - a `DMSWARM` 182862741f57SDave May - fieldname - the textual name to identify this field 1829d3a51819SDave May 183060225df5SJacob Faibussowitsch Output Parameters: 183162741f57SDave May + blocksize - the number of each data type 1832d3a51819SDave May . type - the data type 183362741f57SDave May - data - pointer to raw array 1834d3a51819SDave May 1835d3a51819SDave May Level: beginner 1836d3a51819SDave May 1837d3a51819SDave May Notes: 183820f4b53cSBarry Smith The array must be returned using a matching call to `DMSwarmRestoreField()`. 1839d3a51819SDave May 1840ce78bad3SBarry Smith Fortran Note: 1841ce78bad3SBarry Smith Only works for `type` of `PETSC_SCALAR` 1842ce78bad3SBarry Smith 184320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreField()` 1844d3a51819SDave May @*/ 1845ce78bad3SBarry Smith PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) PeNS 1846d71ae5a4SJacob Faibussowitsch { 1847b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 184877048351SPatrick Sanan DMSwarmDataField gfield; 1849b62e03f8SDave May 1850521f74f9SMatthew G. Knepley PetscFunctionBegin; 1851ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 18529566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 18539566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 18549566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldGetAccess(gfield)); 18559566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldGetEntries(gfield, data)); 1856ad540459SPierre Jolivet if (blocksize) *blocksize = gfield->bs; 1857ad540459SPierre Jolivet if (type) *type = gfield->petsc_type; 18583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1859b62e03f8SDave May } 1860b62e03f8SDave May 1861d3a51819SDave May /*@C 1862d3a51819SDave May DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field 1863d3a51819SDave May 1864ce78bad3SBarry Smith Not Collective 1865d3a51819SDave May 186660225df5SJacob Faibussowitsch Input Parameters: 186720f4b53cSBarry Smith + dm - a `DMSWARM` 186862741f57SDave May - fieldname - the textual name to identify this field 1869d3a51819SDave May 187060225df5SJacob Faibussowitsch Output Parameters: 187162741f57SDave May + blocksize - the number of each data type 1872d3a51819SDave May . type - the data type 187362741f57SDave May - data - pointer to raw array 1874d3a51819SDave May 1875d3a51819SDave May Level: beginner 1876d3a51819SDave May 1877d3a51819SDave May Notes: 187820f4b53cSBarry Smith The user must call `DMSwarmGetField()` prior to calling `DMSwarmRestoreField()`. 1879d3a51819SDave May 1880ce78bad3SBarry Smith Fortran Note: 1881ce78bad3SBarry Smith Only works for `type` of `PETSC_SCALAR` 1882ce78bad3SBarry Smith 188320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetField()` 1884d3a51819SDave May @*/ 1885ce78bad3SBarry Smith PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) PeNS 1886d71ae5a4SJacob Faibussowitsch { 1887b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 188877048351SPatrick Sanan DMSwarmDataField gfield; 1889b62e03f8SDave May 1890521f74f9SMatthew G. Knepley PetscFunctionBegin; 1891ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 18929566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 18939566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldRestoreAccess(gfield)); 1894b62e03f8SDave May if (data) *data = NULL; 18953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1896b62e03f8SDave May } 1897b62e03f8SDave May 18980bf7c1c5SMatthew G. Knepley PetscErrorCode DMSwarmGetFieldInfo(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type) 18990bf7c1c5SMatthew G. Knepley { 19000bf7c1c5SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 19010bf7c1c5SMatthew G. Knepley DMSwarmDataField gfield; 19020bf7c1c5SMatthew G. Knepley 19030bf7c1c5SMatthew G. Knepley PetscFunctionBegin; 19040bf7c1c5SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 19050bf7c1c5SMatthew G. Knepley PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 19060bf7c1c5SMatthew G. Knepley if (blocksize) *blocksize = gfield->bs; 19070bf7c1c5SMatthew G. Knepley if (type) *type = gfield->petsc_type; 19080bf7c1c5SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 19090bf7c1c5SMatthew G. Knepley } 19100bf7c1c5SMatthew G. Knepley 191174d0cae8SMatthew G. Knepley /*@ 191220f4b53cSBarry Smith DMSwarmAddPoint - Add space for one new point in the `DMSWARM` 1913d3a51819SDave May 191420f4b53cSBarry Smith Not Collective 1915d3a51819SDave May 191660225df5SJacob Faibussowitsch Input Parameter: 191720f4b53cSBarry Smith . dm - a `DMSWARM` 1918d3a51819SDave May 1919d3a51819SDave May Level: beginner 1920d3a51819SDave May 1921d3a51819SDave May Notes: 19228b8a3813SDave May The new point will have all fields initialized to zero. 1923d3a51819SDave May 192420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddNPoints()` 1925d3a51819SDave May @*/ 1926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddPoint(DM dm) 1927d71ae5a4SJacob Faibussowitsch { 1928cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1929cb1d1399SDave May 1930521f74f9SMatthew G. Knepley PetscFunctionBegin; 19319566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 19329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0)); 19339566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketAddPoint(swarm->db)); 19349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0)); 19353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1936cb1d1399SDave May } 1937cb1d1399SDave May 193874d0cae8SMatthew G. Knepley /*@ 193920f4b53cSBarry Smith DMSwarmAddNPoints - Add space for a number of new points in the `DMSWARM` 1940d3a51819SDave May 194120f4b53cSBarry Smith Not Collective 1942d3a51819SDave May 194360225df5SJacob Faibussowitsch Input Parameters: 194420f4b53cSBarry Smith + dm - a `DMSWARM` 194562741f57SDave May - npoints - the number of new points to add 1946d3a51819SDave May 1947d3a51819SDave May Level: beginner 1948d3a51819SDave May 1949d3a51819SDave May Notes: 19508b8a3813SDave May The new point will have all fields initialized to zero. 1951d3a51819SDave May 195220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddPoint()` 1953d3a51819SDave May @*/ 1954d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints) 1955d71ae5a4SJacob Faibussowitsch { 1956cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1957cb1d1399SDave May PetscInt nlocal; 1958cb1d1399SDave May 1959521f74f9SMatthew G. Knepley PetscFunctionBegin; 19609566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0)); 19619566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL)); 1962670292f5SMatthew Knepley nlocal = PetscMax(nlocal, 0) + npoints; 19639566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT)); 19649566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0)); 19653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1966cb1d1399SDave May } 1967cb1d1399SDave May 196874d0cae8SMatthew G. Knepley /*@ 196920f4b53cSBarry Smith DMSwarmRemovePoint - Remove the last point from the `DMSWARM` 1970d3a51819SDave May 197120f4b53cSBarry Smith Not Collective 1972d3a51819SDave May 197360225df5SJacob Faibussowitsch Input Parameter: 197420f4b53cSBarry Smith . dm - a `DMSWARM` 1975d3a51819SDave May 1976d3a51819SDave May Level: beginner 1977d3a51819SDave May 197820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePointAtIndex()` 1979d3a51819SDave May @*/ 1980d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePoint(DM dm) 1981d71ae5a4SJacob Faibussowitsch { 1982cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1983cb1d1399SDave May 1984521f74f9SMatthew G. Knepley PetscFunctionBegin; 19859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0)); 19869566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRemovePoint(swarm->db)); 19879566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0)); 19883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1989cb1d1399SDave May } 1990cb1d1399SDave May 199174d0cae8SMatthew G. Knepley /*@ 199220f4b53cSBarry Smith DMSwarmRemovePointAtIndex - Removes a specific point from the `DMSWARM` 1993d3a51819SDave May 199420f4b53cSBarry Smith Not Collective 1995d3a51819SDave May 199660225df5SJacob Faibussowitsch Input Parameters: 199720f4b53cSBarry Smith + dm - a `DMSWARM` 199862741f57SDave May - idx - index of point to remove 1999d3a51819SDave May 2000d3a51819SDave May Level: beginner 2001d3a51819SDave May 200220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()` 2003d3a51819SDave May @*/ 2004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx) 2005d71ae5a4SJacob Faibussowitsch { 2006cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 2007cb1d1399SDave May 2008521f74f9SMatthew G. Knepley PetscFunctionBegin; 20099566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0)); 20109566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx)); 20119566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0)); 20123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2013cb1d1399SDave May } 2014b62e03f8SDave May 201574d0cae8SMatthew G. Knepley /*@ 201620f4b53cSBarry Smith DMSwarmCopyPoint - Copy point pj to point pi in the `DMSWARM` 2017ba4fc9c6SDave May 201820f4b53cSBarry Smith Not Collective 2019ba4fc9c6SDave May 202060225df5SJacob Faibussowitsch Input Parameters: 202120f4b53cSBarry Smith + dm - a `DMSWARM` 2022ba4fc9c6SDave May . pi - the index of the point to copy 2023ba4fc9c6SDave May - pj - the point index where the copy should be located 2024ba4fc9c6SDave May 2025ba4fc9c6SDave May Level: beginner 2026ba4fc9c6SDave May 202720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()` 2028ba4fc9c6SDave May @*/ 2029d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj) 2030d71ae5a4SJacob Faibussowitsch { 2031ba4fc9c6SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 2032ba4fc9c6SDave May 2033ba4fc9c6SDave May PetscFunctionBegin; 20349566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 20359566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj)); 20363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2037ba4fc9c6SDave May } 2038ba4fc9c6SDave May 203966976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points) 2040d71ae5a4SJacob Faibussowitsch { 2041521f74f9SMatthew G. Knepley PetscFunctionBegin; 20429566063dSJacob Faibussowitsch PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points)); 20433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20443454631fSDave May } 20453454631fSDave May 204674d0cae8SMatthew G. Knepley /*@ 204720f4b53cSBarry Smith DMSwarmMigrate - Relocates points defined in the `DMSWARM` to other MPI-ranks 2048d3a51819SDave May 204920f4b53cSBarry Smith Collective 2050d3a51819SDave May 205160225df5SJacob Faibussowitsch Input Parameters: 205220f4b53cSBarry Smith + dm - the `DMSWARM` 205362741f57SDave May - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank 2054d3a51819SDave May 2055d3a51819SDave May Level: advanced 2056d3a51819SDave May 205720f4b53cSBarry Smith Notes: 205820f4b53cSBarry Smith The `DM` will be modified to accommodate received points. 205920f4b53cSBarry Smith If `remove_sent_points` is `PETSC_TRUE`, any points that were sent will be removed from the `DM`. 206020f4b53cSBarry Smith Different styles of migration are supported. See `DMSwarmSetMigrateType()`. 206120f4b53cSBarry Smith 206220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()` 2063d3a51819SDave May @*/ 2064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points) 2065d71ae5a4SJacob Faibussowitsch { 2066f0cdbbbaSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 2067f0cdbbbaSDave May 2068521f74f9SMatthew G. Knepley PetscFunctionBegin; 20699566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0)); 2070f0cdbbbaSDave May switch (swarm->migrate_type) { 2071d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_BASIC: 2072d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points)); 2073d71ae5a4SJacob Faibussowitsch break; 2074d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_DMCELLNSCATTER: 2075d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points)); 2076d71ae5a4SJacob Faibussowitsch break; 2077d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_DMCELLEXACT: 2078d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented"); 2079d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_USER: 2080d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented"); 2081d71ae5a4SJacob Faibussowitsch default: 2082d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown"); 2083f0cdbbbaSDave May } 20849566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0)); 20859566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dm)); 20863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20873454631fSDave May } 20883454631fSDave May 2089f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize); 2090f0cdbbbaSDave May 2091d3a51819SDave May /* 2092d3a51819SDave May DMSwarmCollectViewCreate 2093d3a51819SDave May 2094d3a51819SDave May * Applies a collection method and gathers point neighbour points into dm 2095d3a51819SDave May 2096d3a51819SDave May Notes: 20978b8a3813SDave May Users should call DMSwarmCollectViewDestroy() after 2098d3a51819SDave May they have finished computations associated with the collected points 2099d3a51819SDave May */ 2100d3a51819SDave May 210174d0cae8SMatthew G. Knepley /*@ 2102d3a51819SDave May DMSwarmCollectViewCreate - Applies a collection method and gathers points 210320f4b53cSBarry Smith in neighbour ranks into the `DMSWARM` 2104d3a51819SDave May 210520f4b53cSBarry Smith Collective 2106d3a51819SDave May 210760225df5SJacob Faibussowitsch Input Parameter: 210820f4b53cSBarry Smith . dm - the `DMSWARM` 2109d3a51819SDave May 2110d3a51819SDave May Level: advanced 2111d3a51819SDave May 211220f4b53cSBarry Smith Notes: 211320f4b53cSBarry Smith Users should call `DMSwarmCollectViewDestroy()` after 211420f4b53cSBarry Smith they have finished computations associated with the collected points 21150764c050SBarry Smith 211620f4b53cSBarry Smith Different collect methods are supported. See `DMSwarmSetCollectType()`. 211720f4b53cSBarry Smith 21180764c050SBarry Smith Developer Note: 21190764c050SBarry Smith Create and Destroy routines create new objects that can get destroyed, they do not change the state 21200764c050SBarry Smith of the current object. 21210764c050SBarry Smith 212220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()` 2123d3a51819SDave May @*/ 2124d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewCreate(DM dm) 2125d71ae5a4SJacob Faibussowitsch { 21262712d1f2SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 21272712d1f2SDave May PetscInt ng; 21282712d1f2SDave May 2129521f74f9SMatthew G. Knepley PetscFunctionBegin; 213028b400f6SJacob Faibussowitsch PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active"); 21319566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &ng)); 2132480eef7bSDave May switch (swarm->collect_type) { 2133d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_BASIC: 2134d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng)); 2135d71ae5a4SJacob Faibussowitsch break; 2136d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_DMDABOUNDINGBOX: 2137d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented"); 2138d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_GENERAL: 2139d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented"); 2140d71ae5a4SJacob Faibussowitsch default: 2141d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown"); 2142480eef7bSDave May } 2143480eef7bSDave May swarm->collect_view_active = PETSC_TRUE; 2144480eef7bSDave May swarm->collect_view_reset_nlocal = ng; 21453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21462712d1f2SDave May } 21472712d1f2SDave May 214874d0cae8SMatthew G. Knepley /*@ 214920f4b53cSBarry Smith DMSwarmCollectViewDestroy - Resets the `DMSWARM` to the size prior to calling `DMSwarmCollectViewCreate()` 2150d3a51819SDave May 215120f4b53cSBarry Smith Collective 2152d3a51819SDave May 215360225df5SJacob Faibussowitsch Input Parameters: 215420f4b53cSBarry Smith . dm - the `DMSWARM` 2155d3a51819SDave May 2156d3a51819SDave May Notes: 215720f4b53cSBarry Smith Users should call `DMSwarmCollectViewCreate()` before this function is called. 2158d3a51819SDave May 2159d3a51819SDave May Level: advanced 2160d3a51819SDave May 21610764c050SBarry Smith Developer Note: 21620764c050SBarry Smith Create and Destroy routines create new objects that can get destroyed, they do not change the state 21630764c050SBarry Smith of the current object. 21640764c050SBarry Smith 216520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()` 2166d3a51819SDave May @*/ 2167d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewDestroy(DM dm) 2168d71ae5a4SJacob Faibussowitsch { 21692712d1f2SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 21702712d1f2SDave May 2171521f74f9SMatthew G. Knepley PetscFunctionBegin; 217228b400f6SJacob Faibussowitsch PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active"); 21739566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1)); 2174480eef7bSDave May swarm->collect_view_active = PETSC_FALSE; 21753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21762712d1f2SDave May } 21773454631fSDave May 217866976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmSetUpPIC(DM dm) 2179d71ae5a4SJacob Faibussowitsch { 2180f0cdbbbaSDave May PetscInt dim; 2181f0cdbbbaSDave May 2182521f74f9SMatthew G. Knepley PetscFunctionBegin; 21839566063dSJacob Faibussowitsch PetscCall(DMSwarmSetNumSpecies(dm, 1)); 21849566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 218563a3b9bcSJacob Faibussowitsch PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim); 218663a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim); 21873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2188f0cdbbbaSDave May } 2189f0cdbbbaSDave May 219074d0cae8SMatthew G. Knepley /*@ 219131403186SMatthew G. Knepley DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell 219231403186SMatthew G. Knepley 219320f4b53cSBarry Smith Collective 219431403186SMatthew G. Knepley 219560225df5SJacob Faibussowitsch Input Parameters: 219620f4b53cSBarry Smith + dm - the `DMSWARM` 219720f4b53cSBarry Smith - Npc - The number of particles per cell in the cell `DM` 219831403186SMatthew G. Knepley 219931403186SMatthew G. Knepley Level: intermediate 220031403186SMatthew G. Knepley 220120f4b53cSBarry Smith Notes: 220220f4b53cSBarry Smith The user must use `DMSwarmSetCellDM()` to set the cell `DM` first. The particles are placed randomly inside each cell. If only 220320f4b53cSBarry Smith one particle is in each cell, it is placed at the centroid. 220420f4b53cSBarry Smith 220520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()` 220631403186SMatthew G. Knepley @*/ 2207d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc) 2208d71ae5a4SJacob Faibussowitsch { 220931403186SMatthew G. Knepley DM cdm; 221019307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 221131403186SMatthew G. Knepley PetscRandom rnd; 221231403186SMatthew G. Knepley DMPolytopeType ct; 221331403186SMatthew G. Knepley PetscBool simplex; 221431403186SMatthew G. Knepley PetscReal *centroid, *coords, *xi0, *v0, *J, *invJ, detJ; 221519307e5cSMatthew G. Knepley PetscInt dim, d, cStart, cEnd, c, p, Nfc; 221619307e5cSMatthew G. Knepley const char **coordFields; 221731403186SMatthew G. Knepley 221831403186SMatthew G. Knepley PetscFunctionBeginUser; 22199566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd)); 22209566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0)); 22219566063dSJacob Faibussowitsch PetscCall(PetscRandomSetType(rnd, PETSCRAND48)); 222231403186SMatthew G. Knepley 222319307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(dm, &celldm)); 222419307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields)); 222519307e5cSMatthew G. Knepley PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc); 22269566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &cdm)); 22279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(cdm, &dim)); 22289566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd)); 22299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(cdm, cStart, &ct)); 223031403186SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 223131403186SMatthew G. Knepley 22329566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim, ¢roid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ)); 223331403186SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 223419307e5cSMatthew G. Knepley PetscCall(DMSwarmGetField(dm, coordFields[0], NULL, NULL, (void **)&coords)); 223531403186SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 223631403186SMatthew G. Knepley if (Npc == 1) { 22379566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL)); 223831403186SMatthew G. Knepley for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d]; 223931403186SMatthew G. Knepley } else { 22409566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */ 224131403186SMatthew G. Knepley for (p = 0; p < Npc; ++p) { 224231403186SMatthew G. Knepley const PetscInt n = c * Npc + p; 224331403186SMatthew G. Knepley PetscReal sum = 0.0, refcoords[3]; 224431403186SMatthew G. Knepley 224531403186SMatthew G. Knepley for (d = 0; d < dim; ++d) { 22469566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d])); 224731403186SMatthew G. Knepley sum += refcoords[d]; 224831403186SMatthew G. Knepley } 22499371c9d4SSatish Balay if (simplex && sum > 0.0) 22509371c9d4SSatish Balay for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum; 225131403186SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]); 225231403186SMatthew G. Knepley } 225331403186SMatthew G. Knepley } 225431403186SMatthew G. Knepley } 225519307e5cSMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, coordFields[0], NULL, NULL, (void **)&coords)); 22569566063dSJacob Faibussowitsch PetscCall(PetscFree5(centroid, xi0, v0, J, invJ)); 22579566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rnd)); 22583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225931403186SMatthew G. Knepley } 226031403186SMatthew G. Knepley 226131403186SMatthew G. Knepley /*@ 2262fca3fa51SMatthew G. Knepley DMSwarmGetType - Get particular flavor of `DMSWARM` 2263fca3fa51SMatthew G. Knepley 2264fca3fa51SMatthew G. Knepley Collective 2265fca3fa51SMatthew G. Knepley 2266fca3fa51SMatthew G. Knepley Input Parameter: 2267fca3fa51SMatthew G. Knepley . sw - the `DMSWARM` 2268fca3fa51SMatthew G. Knepley 2269fca3fa51SMatthew G. Knepley Output Parameter: 2270fca3fa51SMatthew G. Knepley . stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`) 2271fca3fa51SMatthew G. Knepley 2272fca3fa51SMatthew G. Knepley Level: advanced 2273fca3fa51SMatthew G. Knepley 2274fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC` 2275fca3fa51SMatthew G. Knepley @*/ 2276fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmGetType(DM sw, DMSwarmType *stype) 2277fca3fa51SMatthew G. Knepley { 2278fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 2279fca3fa51SMatthew G. Knepley 2280fca3fa51SMatthew G. Knepley PetscFunctionBegin; 2281fca3fa51SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 2282fca3fa51SMatthew G. Knepley PetscAssertPointer(stype, 2); 2283fca3fa51SMatthew G. Knepley *stype = swarm->swarm_type; 2284fca3fa51SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2285fca3fa51SMatthew G. Knepley } 2286fca3fa51SMatthew G. Knepley 2287fca3fa51SMatthew G. Knepley /*@ 228820f4b53cSBarry Smith DMSwarmSetType - Set particular flavor of `DMSWARM` 2289d3a51819SDave May 229020f4b53cSBarry Smith Collective 2291d3a51819SDave May 229260225df5SJacob Faibussowitsch Input Parameters: 2293fca3fa51SMatthew G. Knepley + sw - the `DMSWARM` 229420f4b53cSBarry Smith - stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`) 2295d3a51819SDave May 2296d3a51819SDave May Level: advanced 2297d3a51819SDave May 229820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC` 2299d3a51819SDave May @*/ 2300fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM sw, DMSwarmType stype) 2301d71ae5a4SJacob Faibussowitsch { 2302fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 2303f0cdbbbaSDave May 2304521f74f9SMatthew G. Knepley PetscFunctionBegin; 2305fca3fa51SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 2306f0cdbbbaSDave May swarm->swarm_type = stype; 2307fca3fa51SMatthew G. Knepley if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(sw)); 23083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2309f0cdbbbaSDave May } 2310f0cdbbbaSDave May 2311fca3fa51SMatthew G. Knepley static PetscErrorCode DMSwarmCreateRemapDM_Private(DM sw, DM *rdm) 2312d71ae5a4SJacob Faibussowitsch { 2313fca3fa51SMatthew G. Knepley PetscFE fe; 2314fca3fa51SMatthew G. Knepley DMPolytopeType ct; 2315fca3fa51SMatthew G. Knepley PetscInt dim, cStart; 2316fca3fa51SMatthew G. Knepley const char *prefix = "remap_"; 2317fca3fa51SMatthew G. Knepley 2318fca3fa51SMatthew G. Knepley PetscFunctionBegin; 2319fca3fa51SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), rdm)); 2320fca3fa51SMatthew G. Knepley PetscCall(DMSetType(*rdm, DMPLEX)); 2321fca3fa51SMatthew G. Knepley PetscCall(DMPlexSetOptionsPrefix(*rdm, prefix)); 2322fca3fa51SMatthew G. Knepley PetscCall(DMSetFromOptions(*rdm)); 2323fca3fa51SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*rdm, "remap")); 2324fca3fa51SMatthew G. Knepley PetscCall(DMViewFromOptions(*rdm, NULL, "-dm_view")); 2325fca3fa51SMatthew G. Knepley 2326fca3fa51SMatthew G. Knepley PetscCall(DMGetDimension(*rdm, &dim)); 2327fca3fa51SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*rdm, 0, &cStart, NULL)); 2328fca3fa51SMatthew G. Knepley PetscCall(DMPlexGetCellType(*rdm, cStart, &ct)); 2329fca3fa51SMatthew G. Knepley PetscCall(PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, prefix, PETSC_DETERMINE, &fe)); 2330fca3fa51SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)fe, "distribution")); 2331fca3fa51SMatthew G. Knepley PetscCall(DMSetField(*rdm, 0, NULL, (PetscObject)fe)); 2332fca3fa51SMatthew G. Knepley PetscCall(DMCreateDS(*rdm)); 2333fca3fa51SMatthew G. Knepley PetscCall(PetscFEDestroy(&fe)); 2334fca3fa51SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2335fca3fa51SMatthew G. Knepley } 2336fca3fa51SMatthew G. Knepley 2337fca3fa51SMatthew G. Knepley static PetscErrorCode DMSetup_Swarm(DM sw) 2338fca3fa51SMatthew G. Knepley { 2339fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 23403454631fSDave May 2341521f74f9SMatthew G. Knepley PetscFunctionBegin; 23423ba16761SJacob Faibussowitsch if (swarm->issetup) PetscFunctionReturn(PETSC_SUCCESS); 23433454631fSDave May swarm->issetup = PETSC_TRUE; 23443454631fSDave May 2345fca3fa51SMatthew G. Knepley if (swarm->remap_type != DMSWARM_REMAP_NONE) { 2346fca3fa51SMatthew G. Knepley DMSwarmCellDM celldm; 2347fca3fa51SMatthew G. Knepley DM rdm; 2348fca3fa51SMatthew G. Knepley const char *fieldnames[2] = {DMSwarmPICField_coor, "velocity"}; 2349fca3fa51SMatthew G. Knepley const char *vfieldnames[1] = {"w_q"}; 2350fca3fa51SMatthew G. Knepley 2351fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCreateRemapDM_Private(sw, &rdm)); 2352fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(rdm, 1, vfieldnames, 2, fieldnames, &celldm)); 2353fca3fa51SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(sw, celldm)); 2354fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&celldm)); 2355fca3fa51SMatthew G. Knepley PetscCall(DMDestroy(&rdm)); 2356fca3fa51SMatthew G. Knepley } 2357fca3fa51SMatthew G. Knepley 2358f0cdbbbaSDave May if (swarm->swarm_type == DMSWARM_PIC) { 235919307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 2360f0cdbbbaSDave May 2361fca3fa51SMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 2362fca3fa51SMatthew G. Knepley PetscCheck(celldm, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "No active cell DM. DMSWARM_PIC requires you call DMSwarmSetCellDM() or DMSwarmAddCellDM()"); 236319307e5cSMatthew G. Knepley if (celldm->dm->ops->locatepointssubdomain) { 2364f0cdbbbaSDave May /* check methods exists for exact ownership identificiation */ 2365fca3fa51SMatthew G. Knepley PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n")); 2366f0cdbbbaSDave May swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT; 2367f0cdbbbaSDave May } else { 2368f0cdbbbaSDave May /* check methods exist for point location AND rank neighbor identification */ 2369966bd95aSPierre Jolivet PetscCheck(celldm->dm->ops->locatepoints, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined"); 2370fca3fa51SMatthew G. Knepley PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->LocatePoints\n")); 2371f0cdbbbaSDave May 2372966bd95aSPierre Jolivet PetscCheck(celldm->dm->ops->getneighbors, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined"); 2373fca3fa51SMatthew G. Knepley PetscCall(PetscInfo(sw, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n")); 2374f0cdbbbaSDave May 2375f0cdbbbaSDave May swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER; 2376f0cdbbbaSDave May } 2377f0cdbbbaSDave May } 2378f0cdbbbaSDave May 2379fca3fa51SMatthew G. Knepley PetscCall(DMSwarmFinalizeFieldRegister(sw)); 2380f0cdbbbaSDave May 23813454631fSDave May /* check some fields were registered */ 2382fca3fa51SMatthew G. Knepley PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)sw), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()"); 23833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23843454631fSDave May } 23853454631fSDave May 238666976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroy_Swarm(DM dm) 2387d71ae5a4SJacob Faibussowitsch { 238857795646SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 238957795646SDave May 239057795646SDave May PetscFunctionBegin; 23913ba16761SJacob Faibussowitsch if (--swarm->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 239219307e5cSMatthew G. Knepley PetscCall(PetscObjectListDestroy(&swarm->cellDMs)); 239319307e5cSMatthew G. Knepley PetscCall(PetscFree(swarm->activeCellDM)); 23949566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketDestroy(&swarm->db)); 23959566063dSJacob Faibussowitsch PetscCall(PetscFree(swarm)); 23963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 239757795646SDave May } 239857795646SDave May 239966976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer) 2400d71ae5a4SJacob Faibussowitsch { 2401a9ee3421SMatthew G. Knepley DM cdm; 240219307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 2403a9ee3421SMatthew G. Knepley PetscDraw draw; 240431403186SMatthew G. Knepley PetscReal *coords, oldPause, radius = 0.01; 240519307e5cSMatthew G. Knepley PetscInt Np, p, bs, Nfc; 240619307e5cSMatthew G. Knepley const char **coordFields; 2407a9ee3421SMatthew G. Knepley 2408a9ee3421SMatthew G. Knepley PetscFunctionBegin; 24099566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL)); 24109566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 24119566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &cdm)); 24129566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &oldPause)); 24139566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, 0.0)); 24149566063dSJacob Faibussowitsch PetscCall(DMView(cdm, viewer)); 24159566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, oldPause)); 2416a9ee3421SMatthew G. Knepley 241719307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(dm, &celldm)); 241819307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields)); 241919307e5cSMatthew G. Knepley PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc); 24209566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &Np)); 242119307e5cSMatthew G. Knepley PetscCall(DMSwarmGetField(dm, coordFields[0], &bs, NULL, (void **)&coords)); 2422a9ee3421SMatthew G. Knepley for (p = 0; p < Np; ++p) { 2423a9ee3421SMatthew G. Knepley const PetscInt i = p * bs; 2424a9ee3421SMatthew G. Knepley 24259566063dSJacob Faibussowitsch PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE)); 2426a9ee3421SMatthew G. Knepley } 242719307e5cSMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, coordFields[0], &bs, NULL, (void **)&coords)); 24289566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 24299566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 24309566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 24313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2432a9ee3421SMatthew G. Knepley } 2433a9ee3421SMatthew G. Knepley 2434d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer) 2435d71ae5a4SJacob Faibussowitsch { 24366a5217c0SMatthew G. Knepley PetscViewerFormat format; 24376a5217c0SMatthew G. Knepley PetscInt *sizes; 24386a5217c0SMatthew G. Knepley PetscInt dim, Np, maxSize = 17; 24396a5217c0SMatthew G. Knepley MPI_Comm comm; 24406a5217c0SMatthew G. Knepley PetscMPIInt rank, size, p; 244119307e5cSMatthew G. Knepley const char *name, *cellid; 24426a5217c0SMatthew G. Knepley 24436a5217c0SMatthew G. Knepley PetscFunctionBegin; 24446a5217c0SMatthew G. Knepley PetscCall(PetscViewerGetFormat(viewer, &format)); 24456a5217c0SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 24466a5217c0SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(dm, &Np)); 24476a5217c0SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 24486a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 24496a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(comm, &size)); 24506a5217c0SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 245163a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 245263a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 24536a5217c0SMatthew G. Knepley if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes)); 24546a5217c0SMatthew G. Knepley else PetscCall(PetscCalloc1(3, &sizes)); 24556a5217c0SMatthew G. Knepley if (size < maxSize) { 24566a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 24576a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Number of particles per rank:")); 24586a5217c0SMatthew G. Knepley for (p = 0; p < size; ++p) { 24596a5217c0SMatthew G. Knepley if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p])); 24606a5217c0SMatthew G. Knepley } 24616a5217c0SMatthew G. Knepley } else { 24626a5217c0SMatthew G. Knepley PetscInt locMinMax[2] = {Np, Np}; 24636a5217c0SMatthew G. Knepley 24646a5217c0SMatthew G. Knepley PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 24656a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 24666a5217c0SMatthew G. Knepley } 24676a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 24686a5217c0SMatthew G. Knepley PetscCall(PetscFree(sizes)); 24696a5217c0SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO) { 247019307e5cSMatthew G. Knepley DMSwarmCellDM celldm; 24716a5217c0SMatthew G. Knepley PetscInt *cell; 24726a5217c0SMatthew G. Knepley 24736a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Cells containing each particle:\n")); 24746a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 247519307e5cSMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(dm, &celldm)); 247619307e5cSMatthew G. Knepley PetscCall(DMSwarmCellDMGetCellID(celldm, &cellid)); 247719307e5cSMatthew G. Knepley PetscCall(DMSwarmGetField(dm, cellid, NULL, NULL, (void **)&cell)); 247863a3b9bcSJacob Faibussowitsch for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " p%d: %" PetscInt_FMT "\n", p, cell[p])); 24796a5217c0SMatthew G. Knepley PetscCall(PetscViewerFlush(viewer)); 24806a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 248119307e5cSMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, cellid, NULL, NULL, (void **)&cell)); 24826a5217c0SMatthew G. Knepley } 24833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24846a5217c0SMatthew G. Knepley } 24856a5217c0SMatthew G. Knepley 248666976f2fSJacob Faibussowitsch static PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer) 2487d71ae5a4SJacob Faibussowitsch { 24885f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 24899f196a02SMartin Diehl PetscBool isascii, ibinary, isvtk, isdraw, ispython; 24905627991aSBarry Smith #if defined(PETSC_HAVE_HDF5) 24915627991aSBarry Smith PetscBool ishdf5; 24925627991aSBarry Smith #endif 24935f50eb2eSDave May 24945f50eb2eSDave May PetscFunctionBegin; 24955f50eb2eSDave May PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 24965f50eb2eSDave May PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 24979f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 24989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary)); 24999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 25005627991aSBarry Smith #if defined(PETSC_HAVE_HDF5) 25019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 25025627991aSBarry Smith #endif 25039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 25044fc69c0aSMatthew G. Knepley PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython)); 25059f196a02SMartin Diehl if (isascii) { 25066a5217c0SMatthew G. Knepley PetscViewerFormat format; 25076a5217c0SMatthew G. Knepley 25086a5217c0SMatthew G. Knepley PetscCall(PetscViewerGetFormat(viewer, &format)); 25096a5217c0SMatthew G. Knepley switch (format) { 2510d71ae5a4SJacob Faibussowitsch case PETSC_VIEWER_ASCII_INFO_DETAIL: 2511d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT)); 2512d71ae5a4SJacob Faibussowitsch break; 2513d71ae5a4SJacob Faibussowitsch default: 2514d71ae5a4SJacob Faibussowitsch PetscCall(DMView_Swarm_Ascii(dm, viewer)); 25156a5217c0SMatthew G. Knepley } 2516f7d195e4SLawrence Mitchell } else { 25175f50eb2eSDave May #if defined(PETSC_HAVE_HDF5) 251848a46eb9SPierre Jolivet if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer)); 25195f50eb2eSDave May #endif 252048a46eb9SPierre Jolivet if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer)); 25214fc69c0aSMatthew G. Knepley if (ispython) PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)dm)); 2522f7d195e4SLawrence Mitchell } 25233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25245f50eb2eSDave May } 25255f50eb2eSDave May 2526cc4c1da9SBarry Smith /*@ 252720f4b53cSBarry Smith DMSwarmGetCellSwarm - Extracts a single cell from the `DMSWARM` object, returns it as a single cell `DMSWARM`. 252820f4b53cSBarry 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. 2529d0c080abSJoseph Pusztay 2530d0c080abSJoseph Pusztay Noncollective 2531d0c080abSJoseph Pusztay 253260225df5SJacob Faibussowitsch Input Parameters: 253320f4b53cSBarry Smith + sw - the `DMSWARM` 25345627991aSBarry Smith . cellID - the integer id of the cell to be extracted and filtered 253520f4b53cSBarry Smith - cellswarm - The `DMSWARM` to receive the cell 2536d0c080abSJoseph Pusztay 2537d0c080abSJoseph Pusztay Level: beginner 2538d0c080abSJoseph Pusztay 25395627991aSBarry Smith Notes: 254020f4b53cSBarry Smith This presently only supports `DMSWARM_PIC` type 25415627991aSBarry Smith 254220f4b53cSBarry Smith Should be restored with `DMSwarmRestoreCellSwarm()` 2543d0c080abSJoseph Pusztay 254420f4b53cSBarry Smith Changes to this cell of the swarm will be lost if they are made prior to restoring this cell. 254520f4b53cSBarry Smith 254620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreCellSwarm()` 2547d0c080abSJoseph Pusztay @*/ 2548cc4c1da9SBarry Smith PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm) 2549d71ae5a4SJacob Faibussowitsch { 2550d0c080abSJoseph Pusztay DM_Swarm *original = (DM_Swarm *)sw->data; 2551d0c080abSJoseph Pusztay DMLabel label; 2552d0c080abSJoseph Pusztay DM dmc, subdmc; 2553d0c080abSJoseph Pusztay PetscInt *pids, particles, dim; 255419307e5cSMatthew G. Knepley const char *name; 2555d0c080abSJoseph Pusztay 2556d0c080abSJoseph Pusztay PetscFunctionBegin; 2557d0c080abSJoseph Pusztay /* Configure new swarm */ 25589566063dSJacob Faibussowitsch PetscCall(DMSetType(cellswarm, DMSWARM)); 25599566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 25609566063dSJacob Faibussowitsch PetscCall(DMSetDimension(cellswarm, dim)); 25619566063dSJacob Faibussowitsch PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC)); 2562d0c080abSJoseph Pusztay /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */ 25639566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db)); 25649566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 25659566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles)); 25669566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids)); 25679566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db)); 25689566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 2569fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids)); 25709566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(sw, &dmc)); 25719566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label)); 25729566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmc, label)); 25739566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cellID, 1)); 257430cbcd5dSksagiyam PetscCall(DMPlexFilter(dmc, label, 1, PETSC_FALSE, PETSC_FALSE, NULL, &subdmc)); 257519307e5cSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dmc, &name)); 257619307e5cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)subdmc, name)); 25779566063dSJacob Faibussowitsch PetscCall(DMSwarmSetCellDM(cellswarm, subdmc)); 25789566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&label)); 25793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2580d0c080abSJoseph Pusztay } 2581d0c080abSJoseph Pusztay 2582cc4c1da9SBarry Smith /*@ 258320f4b53cSBarry Smith DMSwarmRestoreCellSwarm - Restores a `DMSWARM` object obtained with `DMSwarmGetCellSwarm()`. All fields are copied back into the parent swarm. 2584d0c080abSJoseph Pusztay 2585d0c080abSJoseph Pusztay Noncollective 2586d0c080abSJoseph Pusztay 258760225df5SJacob Faibussowitsch Input Parameters: 258820f4b53cSBarry Smith + sw - the parent `DMSWARM` 2589d0c080abSJoseph Pusztay . cellID - the integer id of the cell to be copied back into the parent swarm 2590d0c080abSJoseph Pusztay - cellswarm - the cell swarm object 2591d0c080abSJoseph Pusztay 2592d0c080abSJoseph Pusztay Level: beginner 2593d0c080abSJoseph Pusztay 25945627991aSBarry Smith Note: 259520f4b53cSBarry Smith This only supports `DMSWARM_PIC` types of `DMSWARM`s 2596d0c080abSJoseph Pusztay 259720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetCellSwarm()` 2598d0c080abSJoseph Pusztay @*/ 2599cc4c1da9SBarry Smith PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm) 2600d71ae5a4SJacob Faibussowitsch { 2601d0c080abSJoseph Pusztay DM dmc; 2602d0c080abSJoseph Pusztay PetscInt *pids, particles, p; 2603d0c080abSJoseph Pusztay 2604d0c080abSJoseph Pusztay PetscFunctionBegin; 26059566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 26069566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids)); 26079566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 2608d0c080abSJoseph Pusztay /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */ 260948a46eb9SPierre Jolivet for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p])); 2610d0c080abSJoseph Pusztay /* Free memory, destroy cell dm */ 26119566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(cellswarm, &dmc)); 26129566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 2613fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids)); 26143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2615d0c080abSJoseph Pusztay } 2616d0c080abSJoseph Pusztay 2617d52c2f21SMatthew G. Knepley /*@ 2618d52c2f21SMatthew G. Knepley DMSwarmComputeMoments - Compute the first three particle moments for a given field 2619d52c2f21SMatthew G. Knepley 2620d52c2f21SMatthew G. Knepley Noncollective 2621d52c2f21SMatthew G. Knepley 2622d52c2f21SMatthew G. Knepley Input Parameters: 2623d52c2f21SMatthew G. Knepley + sw - the `DMSWARM` 2624d52c2f21SMatthew G. Knepley . coordinate - the coordinate field name 2625d52c2f21SMatthew G. Knepley - weight - the weight field name 2626d52c2f21SMatthew G. Knepley 2627d52c2f21SMatthew G. Knepley Output Parameter: 2628d52c2f21SMatthew G. Knepley . moments - the field moments 2629d52c2f21SMatthew G. Knepley 2630d52c2f21SMatthew G. Knepley Level: intermediate 2631d52c2f21SMatthew G. Knepley 2632d52c2f21SMatthew G. Knepley Notes: 2633d52c2f21SMatthew G. Knepley The `moments` array should be of length bs + 2, where bs is the block size of the coordinate field. 2634d52c2f21SMatthew G. Knepley 2635d52c2f21SMatthew G. Knepley The weight field must be a scalar, having blocksize 1. 2636d52c2f21SMatthew G. Knepley 2637d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMPlexComputeMoments()` 2638d52c2f21SMatthew G. Knepley @*/ 2639d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmComputeMoments(DM sw, const char coordinate[], const char weight[], PetscReal moments[]) 2640d52c2f21SMatthew G. Knepley { 2641d52c2f21SMatthew G. Knepley const PetscReal *coords; 2642d52c2f21SMatthew G. Knepley const PetscReal *w; 2643d52c2f21SMatthew G. Knepley PetscReal *mom; 2644d52c2f21SMatthew G. Knepley PetscDataType dtc, dtw; 2645d52c2f21SMatthew G. Knepley PetscInt bsc, bsw, Np; 2646d52c2f21SMatthew G. Knepley MPI_Comm comm; 2647d52c2f21SMatthew G. Knepley 2648d52c2f21SMatthew G. Knepley PetscFunctionBegin; 2649d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 2650d52c2f21SMatthew G. Knepley PetscAssertPointer(coordinate, 2); 2651d52c2f21SMatthew G. Knepley PetscAssertPointer(weight, 3); 2652d52c2f21SMatthew G. Knepley PetscAssertPointer(moments, 4); 2653d52c2f21SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm)); 2654d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, coordinate, &bsc, &dtc, (void **)&coords)); 2655d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, weight, &bsw, &dtw, (void **)&w)); 2656d52c2f21SMatthew G. Knepley PetscCheck(dtc == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s must be real, not %s", coordinate, PetscDataTypes[dtc]); 2657d52c2f21SMatthew G. Knepley PetscCheck(dtw == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be real, not %s", weight, PetscDataTypes[dtw]); 2658d52c2f21SMatthew G. Knepley PetscCheck(bsw == 1, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be a scalar, not blocksize %" PetscInt_FMT, weight, bsw); 2659d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2660d52c2f21SMatthew G. Knepley PetscCall(DMGetWorkArray(sw, bsc + 2, MPIU_REAL, &mom)); 2661d52c2f21SMatthew G. Knepley PetscCall(PetscArrayzero(mom, bsc + 2)); 2662d52c2f21SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 2663d52c2f21SMatthew G. Knepley const PetscReal *c = &coords[p * bsc]; 2664d52c2f21SMatthew G. Knepley const PetscReal wp = w[p]; 2665d52c2f21SMatthew G. Knepley 2666d52c2f21SMatthew G. Knepley mom[0] += wp; 2667d52c2f21SMatthew G. Knepley for (PetscInt d = 0; d < bsc; ++d) { 2668d52c2f21SMatthew G. Knepley mom[d + 1] += wp * c[d]; 2669d52c2f21SMatthew G. Knepley mom[d + bsc + 1] += wp * PetscSqr(c[d]); 2670d52c2f21SMatthew G. Knepley } 2671d52c2f21SMatthew G. Knepley } 2672d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&coords)); 2673d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w)); 2674d52c2f21SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(mom, moments, bsc + 2, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)sw))); 2675d52c2f21SMatthew G. Knepley PetscCall(DMRestoreWorkArray(sw, bsc + 2, MPIU_REAL, &mom)); 2676d0c080abSJoseph Pusztay PetscFunctionReturn(PETSC_SUCCESS); 2677d0c080abSJoseph Pusztay } 2678d0c080abSJoseph Pusztay 2679ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Swarm(DM dm, PetscOptionItems PetscOptionsObject) 2680fca3fa51SMatthew G. Knepley { 2681fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 2682fca3fa51SMatthew G. Knepley 2683fca3fa51SMatthew G. Knepley PetscFunctionBegin; 2684fca3fa51SMatthew G. Knepley PetscOptionsHeadBegin(PetscOptionsObject, "DMSwarm Options"); 2685fca3fa51SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_swarm_remap_type", "Remap algorithm", "DMSwarmSetRemapType", DMSwarmRemapTypeNames, (PetscEnum)swarm->remap_type, (PetscEnum *)&swarm->remap_type, NULL)); 2686fca3fa51SMatthew G. Knepley PetscOptionsHeadEnd(); 2687fca3fa51SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2688fca3fa51SMatthew G. Knepley } 2689fca3fa51SMatthew G. Knepley 2690d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *); 2691d0c080abSJoseph Pusztay 2692d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Swarm(DM sw) 2693d71ae5a4SJacob Faibussowitsch { 2694d0c080abSJoseph Pusztay PetscFunctionBegin; 2695d0c080abSJoseph Pusztay sw->ops->view = DMView_Swarm; 2696d0c080abSJoseph Pusztay sw->ops->load = NULL; 2697fca3fa51SMatthew G. Knepley sw->ops->setfromoptions = DMSetFromOptions_Swarm; 2698d0c080abSJoseph Pusztay sw->ops->clone = DMClone_Swarm; 2699d0c080abSJoseph Pusztay sw->ops->setup = DMSetup_Swarm; 2700d0c080abSJoseph Pusztay sw->ops->createlocalsection = NULL; 2701adc21957SMatthew G. Knepley sw->ops->createsectionpermutation = NULL; 2702d0c080abSJoseph Pusztay sw->ops->createdefaultconstraints = NULL; 2703d0c080abSJoseph Pusztay sw->ops->createglobalvector = DMCreateGlobalVector_Swarm; 2704d0c080abSJoseph Pusztay sw->ops->createlocalvector = DMCreateLocalVector_Swarm; 2705d0c080abSJoseph Pusztay sw->ops->getlocaltoglobalmapping = NULL; 2706d0c080abSJoseph Pusztay sw->ops->createfieldis = NULL; 2707d0c080abSJoseph Pusztay sw->ops->createcoordinatedm = NULL; 270899acd26cSksagiyam sw->ops->createcellcoordinatedm = NULL; 2709d0c080abSJoseph Pusztay sw->ops->getcoloring = NULL; 2710d0c080abSJoseph Pusztay sw->ops->creatematrix = DMCreateMatrix_Swarm; 2711d0c080abSJoseph Pusztay sw->ops->createinterpolation = NULL; 2712d0c080abSJoseph Pusztay sw->ops->createinjection = NULL; 2713d0c080abSJoseph Pusztay sw->ops->createmassmatrix = DMCreateMassMatrix_Swarm; 27141898fd5cSMatthew G. Knepley sw->ops->creategradientmatrix = DMCreateGradientMatrix_Swarm; 2715d0c080abSJoseph Pusztay sw->ops->refine = NULL; 2716d0c080abSJoseph Pusztay sw->ops->coarsen = NULL; 2717d0c080abSJoseph Pusztay sw->ops->refinehierarchy = NULL; 2718d0c080abSJoseph Pusztay sw->ops->coarsenhierarchy = NULL; 27199d50c5ebSMatthew G. Knepley sw->ops->globaltolocalbegin = DMGlobalToLocalBegin_Swarm; 27209d50c5ebSMatthew G. Knepley sw->ops->globaltolocalend = DMGlobalToLocalEnd_Swarm; 27219d50c5ebSMatthew G. Knepley sw->ops->localtoglobalbegin = DMLocalToGlobalBegin_Swarm; 27229d50c5ebSMatthew G. Knepley sw->ops->localtoglobalend = DMLocalToGlobalEnd_Swarm; 2723d0c080abSJoseph Pusztay sw->ops->destroy = DMDestroy_Swarm; 2724d0c080abSJoseph Pusztay sw->ops->createsubdm = NULL; 2725d0c080abSJoseph Pusztay sw->ops->getdimpoints = NULL; 2726d0c080abSJoseph Pusztay sw->ops->locatepoints = NULL; 27279d50c5ebSMatthew G. Knepley sw->ops->projectfieldlocal = DMProjectFieldLocal_Swarm; 27283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2729d0c080abSJoseph Pusztay } 2730d0c080abSJoseph Pusztay 2731d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm) 2732d71ae5a4SJacob Faibussowitsch { 2733d0c080abSJoseph Pusztay DM_Swarm *swarm = (DM_Swarm *)dm->data; 2734d0c080abSJoseph Pusztay 2735d0c080abSJoseph Pusztay PetscFunctionBegin; 2736d0c080abSJoseph Pusztay swarm->refct++; 2737d0c080abSJoseph Pusztay (*newdm)->data = swarm; 27389566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM)); 27399566063dSJacob Faibussowitsch PetscCall(DMInitialize_Swarm(*newdm)); 27402e56dffeSJoe Pusztay (*newdm)->dim = dm->dim; 27413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2742d0c080abSJoseph Pusztay } 2743d0c080abSJoseph Pusztay 2744d3a51819SDave May /*MC 27450b4b7b1cSBarry Smith DMSWARM = "swarm" - A `DM` object for particle methods, such as particle-in-cell (PIC), in which the underlying 27460b4b7b1cSBarry Smith data is both (i) dynamic in length, (ii) and of arbitrary data type. 2747d3a51819SDave May 274820f4b53cSBarry Smith Level: intermediate 274920f4b53cSBarry Smith 275020f4b53cSBarry Smith Notes: 27510b4b7b1cSBarry Smith User data can be represented by `DMSWARM` through a registering "fields" which are to be stored on particles. 275262741f57SDave May To register a field, the user must provide; 275362741f57SDave May (a) a unique name; 275462741f57SDave May (b) the data type (or size in bytes); 275562741f57SDave May (c) the block size of the data. 2756d3a51819SDave May 2757d3a51819SDave May For example, suppose the application requires a unique id, energy, momentum and density to be stored 2758c215a47eSMatthew Knepley on a set of particles. Then the following code could be used 275920f4b53cSBarry Smith .vb 276020f4b53cSBarry Smith DMSwarmInitializeFieldRegister(dm) 276120f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG); 276220f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL); 276320f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL); 276420f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT); 276520f4b53cSBarry Smith DMSwarmFinalizeFieldRegister(dm) 276620f4b53cSBarry Smith .ve 2767d3a51819SDave May 276820f4b53cSBarry Smith The fields represented by `DMSWARM` are dynamic and can be re-sized at any time. 27690b4b7b1cSBarry Smith The only restriction imposed by `DMSWARM` is that all fields contain the same number of particles. 2770d3a51819SDave May 2771d3a51819SDave May To support particle methods, "migration" techniques are provided. These methods migrate data 27725627991aSBarry Smith between ranks. 2773d3a51819SDave May 277420f4b53cSBarry Smith `DMSWARM` supports the methods `DMCreateGlobalVector()` and `DMCreateLocalVector()`. 277520f4b53cSBarry Smith As a `DMSWARM` may internally define and store values of different data types, 277620f4b53cSBarry Smith before calling `DMCreateGlobalVector()` or `DMCreateLocalVector()`, the user must inform `DMSWARM` which 27770b4b7b1cSBarry Smith fields should be used to define a `Vec` object via `DMSwarmVectorDefineField()` 2778c215a47eSMatthew Knepley The specified field can be changed at any time - thereby permitting vectors 2779c215a47eSMatthew Knepley compatible with different fields to be created. 2780d3a51819SDave May 27810b4b7b1cSBarry Smith A dual representation of fields in the `DMSWARM` and a Vec object is permitted via `DMSwarmCreateGlobalVectorFromField()` 27820b4b7b1cSBarry Smith Here the data defining the field in the `DMSWARM` is shared with a `Vec`. 2783d3a51819SDave May This is inherently unsafe if you alter the size of the field at any time between 278420f4b53cSBarry Smith calls to `DMSwarmCreateGlobalVectorFromField()` and `DMSwarmDestroyGlobalVectorFromField()`. 278520f4b53cSBarry Smith If the local size of the `DMSWARM` does not match the local size of the global vector 278620f4b53cSBarry Smith when `DMSwarmDestroyGlobalVectorFromField()` is called, an error is thrown. 2787d3a51819SDave May 27880b4b7b1cSBarry Smith Additional high-level support is provided for Particle-In-Cell methods. Refer to `DMSwarmSetType()`. 278962741f57SDave May 27900b4b7b1cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMType`, `DMCreate()`, `DMSetType()`, `DMSwarmSetType()`, `DMSwarmType`, `DMSwarmCreateGlobalVectorFromField()`, 27910b4b7b1cSBarry Smith `DMCreateGlobalVector()`, `DMCreateLocalVector()` 2792d3a51819SDave May M*/ 2793cc4c1da9SBarry Smith 2794d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm) 2795d71ae5a4SJacob Faibussowitsch { 279657795646SDave May DM_Swarm *swarm; 279757795646SDave May 279857795646SDave May PetscFunctionBegin; 279957795646SDave May PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28004dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&swarm)); 2801f0cdbbbaSDave May dm->data = swarm; 28029566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCreate(&swarm->db)); 28039566063dSJacob Faibussowitsch PetscCall(DMSwarmInitializeFieldRegister(dm)); 2804d52c2f21SMatthew G. Knepley dm->dim = 0; 2805d0c080abSJoseph Pusztay swarm->refct = 1; 28063454631fSDave May swarm->issetup = PETSC_FALSE; 2807480eef7bSDave May swarm->swarm_type = DMSWARM_BASIC; 2808480eef7bSDave May swarm->migrate_type = DMSWARM_MIGRATE_BASIC; 2809480eef7bSDave May swarm->collect_type = DMSWARM_COLLECT_BASIC; 281040c453e9SDave May swarm->migrate_error_on_missing_point = PETSC_FALSE; 2811f0cdbbbaSDave May swarm->collect_view_active = PETSC_FALSE; 2812f0cdbbbaSDave May swarm->collect_view_reset_nlocal = -1; 28139566063dSJacob Faibussowitsch PetscCall(DMInitialize_Swarm(dm)); 28142e956fe4SStefano Zampini if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId)); 28153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 281657795646SDave May } 281719307e5cSMatthew G. Knepley 281819307e5cSMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 281919307e5cSMatthew G. Knepley - Share the DM_Swarm structure 282019307e5cSMatthew G. Knepley */ 282119307e5cSMatthew G. Knepley PetscErrorCode DMSwarmReplace(DM dm, DM *ndm) 282219307e5cSMatthew G. Knepley { 282319307e5cSMatthew G. Knepley DM dmNew = *ndm; 282419307e5cSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 282519307e5cSMatthew G. Knepley PetscInt dim; 282619307e5cSMatthew G. Knepley 282719307e5cSMatthew G. Knepley PetscFunctionBegin; 282819307e5cSMatthew G. Knepley if (dm == dmNew) { 282919307e5cSMatthew G. Knepley PetscCall(DMDestroy(ndm)); 283019307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 283119307e5cSMatthew G. Knepley } 283219307e5cSMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 283319307e5cSMatthew G. Knepley if (!dm->hdr.name) { 283419307e5cSMatthew G. Knepley const char *name; 283519307e5cSMatthew G. Knepley 283619307e5cSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)*ndm, &name)); 283719307e5cSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 283819307e5cSMatthew G. Knepley } 283919307e5cSMatthew G. Knepley PetscCall(DMGetDimension(dmNew, &dim)); 284019307e5cSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 284119307e5cSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 284219307e5cSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 284319307e5cSMatthew G. Knepley PetscCall(DMDestroy_Swarm(dm)); 284419307e5cSMatthew G. Knepley PetscCall(DMInitialize_Swarm(dm)); 284519307e5cSMatthew G. Knepley dm->data = dmNew->data; 284619307e5cSMatthew G. Knepley ((DM_Swarm *)dmNew->data)->refct++; 284719307e5cSMatthew G. Knepley PetscCall(DMDestroy(ndm)); 284819307e5cSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 284919307e5cSMatthew G. Knepley } 2850fca3fa51SMatthew G. Knepley 2851fca3fa51SMatthew G. Knepley /*@ 2852fca3fa51SMatthew G. Knepley DMSwarmDuplicate - Creates a new `DMSWARM` with the same fields and cell `DM`s but no particles 2853fca3fa51SMatthew G. Knepley 2854fca3fa51SMatthew G. Knepley Collective 2855fca3fa51SMatthew G. Knepley 2856fca3fa51SMatthew G. Knepley Input Parameter: 2857fca3fa51SMatthew G. Knepley . sw - the `DMSWARM` 2858fca3fa51SMatthew G. Knepley 2859fca3fa51SMatthew G. Knepley Output Parameter: 2860fca3fa51SMatthew G. Knepley . nsw - the new `DMSWARM` 2861fca3fa51SMatthew G. Knepley 2862fca3fa51SMatthew G. Knepley Level: beginner 2863fca3fa51SMatthew G. Knepley 2864fca3fa51SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmCreate()`, `DMClone()` 2865fca3fa51SMatthew G. Knepley @*/ 2866fca3fa51SMatthew G. Knepley PetscErrorCode DMSwarmDuplicate(DM sw, DM *nsw) 2867fca3fa51SMatthew G. Knepley { 2868fca3fa51SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 2869fca3fa51SMatthew G. Knepley DMSwarmDataField *fields; 2870fca3fa51SMatthew G. Knepley DMSwarmCellDM celldm, ncelldm; 2871fca3fa51SMatthew G. Knepley DMSwarmType stype; 2872fca3fa51SMatthew G. Knepley const char *name, **celldmnames; 2873fca3fa51SMatthew G. Knepley void *ctx; 2874fca3fa51SMatthew G. Knepley PetscInt dim, Nf, Ndm; 2875fca3fa51SMatthew G. Knepley PetscBool flg; 2876fca3fa51SMatthew G. Knepley 2877fca3fa51SMatthew G. Knepley PetscFunctionBegin; 2878fca3fa51SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)sw), nsw)); 2879fca3fa51SMatthew G. Knepley PetscCall(DMSetType(*nsw, DMSWARM)); 2880fca3fa51SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)sw, &name)); 2881fca3fa51SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)*nsw, name)); 2882fca3fa51SMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 2883fca3fa51SMatthew G. Knepley PetscCall(DMSetDimension(*nsw, dim)); 2884fca3fa51SMatthew G. Knepley PetscCall(DMSwarmGetType(sw, &stype)); 2885fca3fa51SMatthew G. Knepley PetscCall(DMSwarmSetType(*nsw, stype)); 2886fca3fa51SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 2887fca3fa51SMatthew G. Knepley PetscCall(DMSetApplicationContext(*nsw, ctx)); 2888fca3fa51SMatthew G. Knepley 2889fca3fa51SMatthew G. Knepley PetscCall(DMSwarmDataBucketGetDMSwarmDataFields(swarm->db, &Nf, &fields)); 2890fca3fa51SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 2891fca3fa51SMatthew G. Knepley PetscCall(DMSwarmDataFieldStringInList(fields[f]->name, ((DM_Swarm *)(*nsw)->data)->db->nfields, (const DMSwarmDataField *)((DM_Swarm *)(*nsw)->data)->db->field, &flg)); 2892fca3fa51SMatthew G. Knepley if (!flg) PetscCall(DMSwarmRegisterPetscDatatypeField(*nsw, fields[f]->name, fields[f]->bs, fields[f]->petsc_type)); 2893fca3fa51SMatthew G. Knepley } 2894fca3fa51SMatthew G. Knepley 2895fca3fa51SMatthew G. Knepley PetscCall(DMSwarmGetCellDMNames(sw, &Ndm, &celldmnames)); 2896fca3fa51SMatthew G. Knepley for (PetscInt c = 0; c < Ndm; ++c) { 2897fca3fa51SMatthew G. Knepley DM dm; 2898fca3fa51SMatthew G. Knepley PetscInt Ncf; 2899fca3fa51SMatthew G. Knepley const char **coordfields, **fields; 2900fca3fa51SMatthew G. Knepley 2901fca3fa51SMatthew G. Knepley PetscCall(DMSwarmGetCellDMByName(sw, celldmnames[c], &celldm)); 2902fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCellDMGetDM(celldm, &dm)); 2903fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Ncf, &coordfields)); 2904fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCellDMGetFields(celldm, &Nf, &fields)); 2905fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCellDMCreate(dm, Nf, fields, Ncf, coordfields, &ncelldm)); 2906fca3fa51SMatthew G. Knepley PetscCall(DMSwarmAddCellDM(*nsw, ncelldm)); 2907fca3fa51SMatthew G. Knepley PetscCall(DMSwarmCellDMDestroy(&ncelldm)); 2908fca3fa51SMatthew G. Knepley } 2909fca3fa51SMatthew G. Knepley PetscCall(PetscFree(celldmnames)); 2910fca3fa51SMatthew G. Knepley 2911fca3fa51SMatthew G. Knepley PetscCall(DMSetFromOptions(*nsw)); 2912fca3fa51SMatthew G. Knepley PetscCall(DMSetUp(*nsw)); 2913fca3fa51SMatthew G. Knepley PetscCall(DMSwarmGetCellDMActive(sw, &celldm)); 2914fca3fa51SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)celldm, &name)); 2915fca3fa51SMatthew G. Knepley PetscCall(DMSwarmSetCellDMActive(*nsw, name)); 2916fca3fa51SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 2917fca3fa51SMatthew G. Knepley } 29189d50c5ebSMatthew G. Knepley 29199d50c5ebSMatthew G. Knepley PetscErrorCode DMLocalToGlobalBegin_Swarm(DM dm, Vec l, InsertMode mode, Vec g) 29209d50c5ebSMatthew G. Knepley { 29219d50c5ebSMatthew G. Knepley PetscFunctionBegin; 29229d50c5ebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 29239d50c5ebSMatthew G. Knepley } 29249d50c5ebSMatthew G. Knepley 29259d50c5ebSMatthew G. Knepley PetscErrorCode DMLocalToGlobalEnd_Swarm(DM dm, Vec l, InsertMode mode, Vec g) 29269d50c5ebSMatthew G. Knepley { 29279d50c5ebSMatthew G. Knepley PetscFunctionBegin; 29289d50c5ebSMatthew G. Knepley switch (mode) { 29299d50c5ebSMatthew G. Knepley case INSERT_VALUES: 29309d50c5ebSMatthew G. Knepley PetscCall(VecCopy(l, g)); 29319d50c5ebSMatthew G. Knepley break; 29329d50c5ebSMatthew G. Knepley case ADD_VALUES: 29339d50c5ebSMatthew G. Knepley PetscCall(VecAXPY(g, 1., l)); 29349d50c5ebSMatthew G. Knepley break; 29359d50c5ebSMatthew G. Knepley default: 29369d50c5ebSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mode not supported: %d", mode); 29379d50c5ebSMatthew G. Knepley } 29389d50c5ebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 29399d50c5ebSMatthew G. Knepley } 29409d50c5ebSMatthew G. Knepley 29419d50c5ebSMatthew G. Knepley PetscErrorCode DMGlobalToLocalBegin_Swarm(DM dm, Vec g, InsertMode mode, Vec l) 29429d50c5ebSMatthew G. Knepley { 29439d50c5ebSMatthew G. Knepley PetscFunctionBegin; 29449d50c5ebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 29459d50c5ebSMatthew G. Knepley } 29469d50c5ebSMatthew G. Knepley 29479d50c5ebSMatthew G. Knepley PetscErrorCode DMGlobalToLocalEnd_Swarm(DM dm, Vec g, InsertMode mode, Vec l) 29489d50c5ebSMatthew G. Knepley { 29499d50c5ebSMatthew G. Knepley PetscFunctionBegin; 29509d50c5ebSMatthew G. Knepley PetscCall(DMLocalToGlobalEnd_Swarm(dm, g, mode, l)); 29519d50c5ebSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 29529d50c5ebSMatthew G. Knepley } 2953