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