1d52c2f21SMatthew G. Knepley #include "petscsys.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}; 21ea78f98cSLisandro Dalcin const char *DMSwarmPICLayoutTypeNames[] = {"regular", "gauss", "subdivision", NULL}; 22f0cdbbbaSDave May 23f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid"; 24f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank"; 25f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor"; 26e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid"; 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 33d52c2f21SMatthew G. Knepley static PetscErrorCode DMInitialize_Swarm(DM); 34d52c2f21SMatthew G. Knepley static PetscErrorCode DMDestroy_Swarm(DM); 35d52c2f21SMatthew G. Knepley 36d52c2f21SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 37d52c2f21SMatthew G. Knepley - Share the DM_Swarm structure 38d52c2f21SMatthew G. Knepley */ 39d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmReplace_Internal(DM dm, DM *ndm) 40d52c2f21SMatthew G. Knepley { 41d52c2f21SMatthew G. Knepley DM dmNew = *ndm; 42d52c2f21SMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 43d52c2f21SMatthew G. Knepley PetscInt dim; 44d52c2f21SMatthew G. Knepley 45d52c2f21SMatthew G. Knepley PetscFunctionBegin; 46d52c2f21SMatthew G. Knepley if (dm == dmNew) { 47d52c2f21SMatthew G. Knepley PetscCall(DMDestroy(ndm)); 48d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 49d52c2f21SMatthew G. Knepley } 50d52c2f21SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 51d52c2f21SMatthew G. Knepley if (!dm->hdr.name) { 52d52c2f21SMatthew G. Knepley const char *name; 53d52c2f21SMatthew G. Knepley 54d52c2f21SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)*ndm, &name)); 55d52c2f21SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 56d52c2f21SMatthew G. Knepley } 57d52c2f21SMatthew G. Knepley PetscCall(DMGetDimension(dmNew, &dim)); 58d52c2f21SMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 59d52c2f21SMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 60d52c2f21SMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 61d52c2f21SMatthew G. Knepley PetscCall(DMDestroy_Swarm(dm)); 62d52c2f21SMatthew G. Knepley PetscCall(DMInitialize_Swarm(dm)); 63d52c2f21SMatthew G. Knepley dm->data = dmNew->data; 64d52c2f21SMatthew G. Knepley ((DM_Swarm *)dmNew->data)->refct++; 65d52c2f21SMatthew G. Knepley PetscCall(DMDestroy(ndm)); 66d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 67d52c2f21SMatthew G. Knepley } 68d52c2f21SMatthew G. Knepley 6966976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer) 70d71ae5a4SJacob Faibussowitsch { 7174d0cae8SMatthew G. Knepley DM dm; 7274d0cae8SMatthew G. Knepley PetscReal seqval; 7374d0cae8SMatthew G. Knepley PetscInt seqnum, bs; 74eb0c6899SMatthew G. Knepley PetscBool isseq, ists; 7574d0cae8SMatthew G. Knepley 7674d0cae8SMatthew G. Knepley PetscFunctionBegin; 779566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 789566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &bs)); 799566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields")); 809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 819566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval)); 82eb0c6899SMatthew G. Knepley PetscCall(PetscViewerHDF5IsTimestepping(viewer, &ists)); 83eb0c6899SMatthew G. Knepley if (ists) PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); 849566063dSJacob Faibussowitsch /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */ 859566063dSJacob Faibussowitsch PetscCall(VecViewNative(v, viewer)); 869566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs)); 879566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PopGroup(viewer)); 883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8974d0cae8SMatthew G. Knepley } 9074d0cae8SMatthew G. Knepley 9166976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer) 92d71ae5a4SJacob Faibussowitsch { 9374d0cae8SMatthew G. Knepley Vec coordinates; 9474d0cae8SMatthew G. Knepley PetscInt Np; 9574d0cae8SMatthew G. Knepley PetscBool isseq; 96d52c2f21SMatthew G. Knepley const char *coordname; 9774d0cae8SMatthew G. Knepley 9874d0cae8SMatthew G. Knepley PetscFunctionBegin; 99d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetCoordinateField(dm, &coordname)); 1009566063dSJacob Faibussowitsch PetscCall(DMSwarmGetSize(dm, &Np)); 101d52c2f21SMatthew G. Knepley PetscCall(DMSwarmCreateGlobalVectorFromField(dm, coordname, &coordinates)); 1029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 1039566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles")); 1049566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq)); 1059566063dSJacob Faibussowitsch PetscCall(VecViewNative(coordinates, viewer)); 1069566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np)); 1079566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PopGroup(viewer)); 108d52c2f21SMatthew G. Knepley PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, coordname, &coordinates)); 1093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11074d0cae8SMatthew G. Knepley } 11174d0cae8SMatthew G. Knepley #endif 11274d0cae8SMatthew G. Knepley 11366976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer) 114d71ae5a4SJacob Faibussowitsch { 11574d0cae8SMatthew G. Knepley DM dm; 116f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5) 11774d0cae8SMatthew G. Knepley PetscBool ishdf5; 118f9558f5cSBarry Smith #endif 11974d0cae8SMatthew G. Knepley 12074d0cae8SMatthew G. Knepley PetscFunctionBegin; 1219566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 12228b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 123f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5) 1249566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 12574d0cae8SMatthew G. Knepley if (ishdf5) { 1269566063dSJacob Faibussowitsch PetscCall(VecView_Swarm_HDF5_Internal(v, viewer)); 1273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12874d0cae8SMatthew G. Knepley } 129f9558f5cSBarry Smith #endif 1309566063dSJacob Faibussowitsch PetscCall(VecViewNative(v, viewer)); 1313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13274d0cae8SMatthew G. Knepley } 13374d0cae8SMatthew G. Knepley 134d52c2f21SMatthew G. Knepley /*@C 135d52c2f21SMatthew G. Knepley DMSwarmVectorGetField - Gets the fields from which to define a `Vec` object 1360bf7c1c5SMatthew G. Knepley when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 1370bf7c1c5SMatthew G. Knepley 1380bf7c1c5SMatthew G. Knepley Not collective 1390bf7c1c5SMatthew G. Knepley 1400bf7c1c5SMatthew G. Knepley Input Parameter: 1410bf7c1c5SMatthew G. Knepley . dm - a `DMSWARM` 1420bf7c1c5SMatthew G. Knepley 143d52c2f21SMatthew G. Knepley Output Parameters: 144d52c2f21SMatthew G. Knepley + Nf - the number of fields 145d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field, or NULL if it has not been set 1460bf7c1c5SMatthew G. Knepley 1470bf7c1c5SMatthew G. Knepley Level: beginner 1480bf7c1c5SMatthew G. Knepley 149d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 1500bf7c1c5SMatthew G. Knepley @*/ 151d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmVectorGetField(DM dm, PetscInt *Nf, const char **fieldnames[]) 1520bf7c1c5SMatthew G. Knepley { 1530bf7c1c5SMatthew G. Knepley PetscFunctionBegin; 1540bf7c1c5SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 155d52c2f21SMatthew G. Knepley if (Nf) { 156d52c2f21SMatthew G. Knepley PetscAssertPointer(Nf, 2); 157d52c2f21SMatthew G. Knepley *Nf = ((DM_Swarm *)dm->data)->vec_field_num; 158d52c2f21SMatthew G. Knepley } 159d52c2f21SMatthew G. Knepley if (fieldnames) { 160d52c2f21SMatthew G. Knepley PetscAssertPointer(fieldnames, 3); 161d52c2f21SMatthew G. Knepley *fieldnames = ((DM_Swarm *)dm->data)->vec_field_names; 162d52c2f21SMatthew G. Knepley } 1630bf7c1c5SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1640bf7c1c5SMatthew G. Knepley } 1650bf7c1c5SMatthew G. Knepley 166cc4c1da9SBarry Smith /*@ 16720f4b53cSBarry Smith DMSwarmVectorDefineField - Sets the field from which to define a `Vec` object 16820f4b53cSBarry Smith when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 16957795646SDave May 17020f4b53cSBarry Smith Collective 17157795646SDave May 17260225df5SJacob Faibussowitsch Input Parameters: 17320f4b53cSBarry Smith + dm - a `DMSWARM` 174d52c2f21SMatthew G. Knepley - fieldname - the textual name given to each registered field 17557795646SDave May 176d3a51819SDave May Level: beginner 17757795646SDave May 178d3a51819SDave May Notes: 17920f4b53cSBarry Smith The field with name `fieldname` must be defined as having a data type of `PetscScalar`. 180e7af74c8SDave May 18120f4b53cSBarry Smith This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`. 18220f4b53cSBarry Smith Multiple calls to `DMSwarmVectorDefineField()` are permitted. 183e7af74c8SDave May 184d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineFields()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 185d3a51819SDave May @*/ 186d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[]) 187d71ae5a4SJacob Faibussowitsch { 188d52c2f21SMatthew G. Knepley PetscFunctionBegin; 189d52c2f21SMatthew G. Knepley PetscCall(DMSwarmVectorDefineFields(dm, 1, &fieldname)); 190d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 191d52c2f21SMatthew G. Knepley } 192d52c2f21SMatthew G. Knepley 193d52c2f21SMatthew G. Knepley /*@C 194d52c2f21SMatthew G. Knepley DMSwarmVectorDefineFields - Sets the fields from which to define a `Vec` object 195d52c2f21SMatthew G. Knepley when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 196d52c2f21SMatthew G. Knepley 197d52c2f21SMatthew G. Knepley Collective, No Fortran support 198d52c2f21SMatthew G. Knepley 199d52c2f21SMatthew G. Knepley Input Parameters: 200d52c2f21SMatthew G. Knepley + dm - a `DMSWARM` 201d52c2f21SMatthew G. Knepley . Nf - the number of fields 202d52c2f21SMatthew G. Knepley - fieldnames - the textual name given to each registered field 203d52c2f21SMatthew G. Knepley 204d52c2f21SMatthew G. Knepley Level: beginner 205d52c2f21SMatthew G. Knepley 206d52c2f21SMatthew G. Knepley Notes: 207d52c2f21SMatthew G. Knepley Each field with name in `fieldnames` must be defined as having a data type of `PetscScalar`. 208d52c2f21SMatthew G. Knepley 209d52c2f21SMatthew G. Knepley This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`. 210d52c2f21SMatthew G. Knepley Multiple calls to `DMSwarmVectorDefineField()` are permitted. 211d52c2f21SMatthew G. Knepley 212d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 213d52c2f21SMatthew G. Knepley @*/ 214d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineFields(DM dm, PetscInt Nf, const char *fieldnames[]) 215d52c2f21SMatthew G. Knepley { 216d52c2f21SMatthew G. Knepley DM_Swarm *sw = (DM_Swarm *)dm->data; 217b5bcf523SDave May 218a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 2190bf7c1c5SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 220d52c2f21SMatthew G. Knepley if (fieldnames) PetscAssertPointer(fieldnames, 3); 221d52c2f21SMatthew G. Knepley if (!sw->issetup) PetscCall(DMSetUp(dm)); 222d52c2f21SMatthew G. Knepley PetscCheck(Nf >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields must be non-negative, not %" PetscInt_FMT, Nf); 223d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < sw->vec_field_num; ++f) PetscCall(PetscFree(sw->vec_field_names[f])); 224d52c2f21SMatthew G. Knepley PetscCall(PetscFree(sw->vec_field_names)); 225b5bcf523SDave May 226d52c2f21SMatthew G. Knepley sw->vec_field_num = Nf; 227d52c2f21SMatthew G. Knepley sw->vec_field_bs = 0; 228d52c2f21SMatthew G. Knepley PetscCall(DMSwarmDataBucketGetSizes(sw->db, &sw->vec_field_nlocal, NULL, NULL)); 229d52c2f21SMatthew G. Knepley PetscCall(PetscMalloc1(Nf, &sw->vec_field_names)); 230d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 231d52c2f21SMatthew G. Knepley PetscInt bs; 232d52c2f21SMatthew G. Knepley PetscScalar *array; 233d52c2f21SMatthew G. Knepley PetscDataType type; 234d52c2f21SMatthew G. Knepley 235d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(dm, fieldnames[f], &bs, &type, (void **)&array)); 236d52c2f21SMatthew G. Knepley // Check all fields are of type PETSC_REAL or PETSC_SCALAR 23708401ef6SPierre Jolivet PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 238d52c2f21SMatthew G. Knepley sw->vec_field_bs += bs; 239d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, fieldnames[f], &bs, &type, (void **)&array)); 240d52c2f21SMatthew G. Knepley PetscCall(PetscStrallocpy(fieldnames[f], (char **)&sw->vec_field_names[f])); 241d52c2f21SMatthew G. Knepley } 2423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 243b5bcf523SDave May } 244b5bcf523SDave May 245cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */ 24666976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Swarm(DM dm, Vec *vec) 247d71ae5a4SJacob Faibussowitsch { 248b5bcf523SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 249b5bcf523SDave May Vec x; 250b5bcf523SDave May char name[PETSC_MAX_PATH_LEN]; 251b5bcf523SDave May 252a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 2539566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 254d52c2f21SMatthew G. Knepley PetscCheck(swarm->vec_field_num, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField(s) first"); 255d52c2f21SMatthew G. Knepley PetscCheck(swarm->vec_field_nlocal == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since last call to VectorDefineField(s) first"); /* Stale data */ 256cc651181SDave May 257d52c2f21SMatthew G. Knepley PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN)); 258d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < swarm->vec_field_num; ++f) { 259d52c2f21SMatthew G. Knepley PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN)); 260d52c2f21SMatthew G. Knepley PetscCall(PetscStrlcat(name, swarm->vec_field_names[f], PETSC_MAX_PATH_LEN)); 261d52c2f21SMatthew G. Knepley } 2629566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &x)); 2639566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)x, name)); 2649566063dSJacob Faibussowitsch PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE)); 2659566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(x, swarm->vec_field_bs)); 2669566063dSJacob Faibussowitsch PetscCall(VecSetDM(x, dm)); 2679566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(x)); 2689566063dSJacob Faibussowitsch PetscCall(VecSetDM(x, dm)); 2699566063dSJacob Faibussowitsch PetscCall(VecSetOperation(x, VECOP_VIEW, (void (*)(void))VecView_Swarm)); 270b5bcf523SDave May *vec = x; 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 272b5bcf523SDave May } 273b5bcf523SDave May 274b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */ 27566976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Swarm(DM dm, Vec *vec) 276d71ae5a4SJacob Faibussowitsch { 277b5bcf523SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 278b5bcf523SDave May Vec x; 279b5bcf523SDave May char name[PETSC_MAX_PATH_LEN]; 280b5bcf523SDave May 281a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 2829566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 283d52c2f21SMatthew G. Knepley PetscCheck(swarm->vec_field_num, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField(s) first"); 284d52c2f21SMatthew G. Knepley PetscCheck(swarm->vec_field_nlocal == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since last call to VectorDefineField(s) first"); 285cc651181SDave May 286d52c2f21SMatthew G. Knepley PetscCall(PetscStrncpy(name, "DMSwarmField", PETSC_MAX_PATH_LEN)); 287d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < swarm->vec_field_num; ++f) { 288d52c2f21SMatthew G. Knepley PetscCall(PetscStrlcat(name, "_", PETSC_MAX_PATH_LEN)); 289d52c2f21SMatthew G. Knepley PetscCall(PetscStrlcat(name, swarm->vec_field_names[f], PETSC_MAX_PATH_LEN)); 290d52c2f21SMatthew G. Knepley } 2919566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &x)); 2929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)x, name)); 2939566063dSJacob Faibussowitsch PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE)); 2949566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(x, swarm->vec_field_bs)); 2959566063dSJacob Faibussowitsch PetscCall(VecSetDM(x, dm)); 2969566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(x)); 297b5bcf523SDave May *vec = x; 2983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 299b5bcf523SDave May } 300b5bcf523SDave May 301d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec) 302d71ae5a4SJacob Faibussowitsch { 303fb1bcc12SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 30477048351SPatrick Sanan DMSwarmDataField gfield; 3052e956fe4SStefano Zampini PetscInt bs, nlocal, fid = -1, cfid = -2; 3062e956fe4SStefano Zampini PetscBool flg; 307d3a51819SDave May 308fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 3092e956fe4SStefano Zampini /* check vector is an inplace array */ 3102e956fe4SStefano Zampini PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid)); 3112e956fe4SStefano Zampini PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg)); 312ea17275aSJose E. Roman (void)flg; /* avoid compiler warning */ 313e978a55eSPierre 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); 3149566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(*vec, &nlocal)); 3159566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(*vec, &bs)); 31608401ef6SPierre 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"); 3179566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 3189566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldRestoreAccess(gfield)); 3198df78e51SMark Adams PetscCall(VecResetArray(*vec)); 3209566063dSJacob Faibussowitsch PetscCall(VecDestroy(vec)); 3213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 322fb1bcc12SMatthew G. Knepley } 323fb1bcc12SMatthew G. Knepley 324d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec) 325d71ae5a4SJacob Faibussowitsch { 326fb1bcc12SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 327fb1bcc12SMatthew G. Knepley PetscDataType type; 328fb1bcc12SMatthew G. Knepley PetscScalar *array; 3292e956fe4SStefano Zampini PetscInt bs, n, fid; 330fb1bcc12SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 331e4fbd051SBarry Smith PetscMPIInt size; 332*7f92dde0SRylanor PetscBool iscuda, iskokkos, iship; 333fb1bcc12SMatthew G. Knepley 334fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 3359566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 3369566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL)); 3379566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array)); 33808401ef6SPierre Jolivet PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 339fb1bcc12SMatthew G. Knepley 3409566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 3418df78e51SMark Adams PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos)); 3428df78e51SMark Adams PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda)); 343*7f92dde0SRylanor PetscCall(PetscStrcmp(dm->vectype, VECHIP, &iship)); 3448df78e51SMark Adams PetscCall(VecCreate(comm, vec)); 3458df78e51SMark Adams PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE)); 3468df78e51SMark Adams PetscCall(VecSetBlockSize(*vec, bs)); 3478df78e51SMark Adams if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS)); 3488df78e51SMark Adams else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA)); 349*7f92dde0SRylanor else if (iship) PetscCall(VecSetType(*vec, VECHIP)); 3508df78e51SMark Adams else PetscCall(VecSetType(*vec, VECSTANDARD)); 3518df78e51SMark Adams PetscCall(VecPlaceArray(*vec, array)); 3528df78e51SMark Adams 3539566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname)); 3549566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*vec, name)); 355fb1bcc12SMatthew G. Knepley 356fb1bcc12SMatthew G. Knepley /* Set guard */ 3572e956fe4SStefano Zampini PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid)); 3582e956fe4SStefano Zampini PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid)); 35974d0cae8SMatthew G. Knepley 3609566063dSJacob Faibussowitsch PetscCall(VecSetDM(*vec, dm)); 3619566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm)); 3623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 363fb1bcc12SMatthew G. Knepley } 364fb1bcc12SMatthew G. Knepley 3650643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by 3660643ed39SMatthew G. Knepley 3670643ed39SMatthew G. Knepley \hat f = \sum_i f_i \phi_i 3680643ed39SMatthew G. Knepley 3690643ed39SMatthew G. Knepley and a particle function is given by 3700643ed39SMatthew G. Knepley 3710643ed39SMatthew G. Knepley f = \sum_i w_i \delta(x - x_i) 3720643ed39SMatthew G. Knepley 3730643ed39SMatthew G. Knepley then we want to require that 3740643ed39SMatthew G. Knepley 3750643ed39SMatthew G. Knepley M \hat f = M_p f 3760643ed39SMatthew G. Knepley 3770643ed39SMatthew G. Knepley where the particle mass matrix is given by 3780643ed39SMatthew G. Knepley 3790643ed39SMatthew G. Knepley (M_p)_{ij} = \int \phi_i \delta(x - x_j) 3800643ed39SMatthew G. Knepley 3810643ed39SMatthew G. Knepley The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in 3820643ed39SMatthew G. Knepley his integral. We allow this with the boolean flag. 3830643ed39SMatthew G. Knepley */ 384d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) 385d71ae5a4SJacob Faibussowitsch { 38683c47955SMatthew G. Knepley const char *name = "Mass Matrix"; 3870643ed39SMatthew G. Knepley MPI_Comm comm; 38883c47955SMatthew G. Knepley PetscDS prob; 38983c47955SMatthew G. Knepley PetscSection fsection, globalFSection; 390e8f14785SLisandro Dalcin PetscHSetIJ ht; 3910643ed39SMatthew G. Knepley PetscLayout rLayout, colLayout; 39283c47955SMatthew G. Knepley PetscInt *dnz, *onz; 393adb2528bSMark Adams PetscInt locRows, locCols, rStart, colStart, colEnd, *rowIDXs; 3940643ed39SMatthew G. Knepley PetscReal *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0}; 39583c47955SMatthew G. Knepley PetscScalar *elemMat; 3960bf7c1c5SMatthew G. Knepley PetscInt dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0, totNc = 0; 397d52c2f21SMatthew G. Knepley const char *coordname; 39883c47955SMatthew G. Knepley 39983c47955SMatthew G. Knepley PetscFunctionBegin; 4009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mass, &comm)); 4019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmf, &dim)); 4029566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmf, &prob)); 4039566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 4049566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim)); 4059566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ)); 4069566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection)); 4079566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 4089566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd)); 4099566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mass, &locRows, &locCols)); 41083c47955SMatthew G. Knepley 411d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetCoordinateField(dmc, &coordname)); 412d52c2f21SMatthew G. Knepley 4139566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &colLayout)); 4149566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(colLayout, locCols)); 4159566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(colLayout, 1)); 4169566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colLayout)); 4179566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd)); 4189566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&colLayout)); 4190643ed39SMatthew G. Knepley 4209566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 4219566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 4229566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 4239566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 4249566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL)); 4259566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 4260643ed39SMatthew G. Knepley 4279566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz)); 4289566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&ht)); 42953e60ab4SJoseph Pusztay 4309566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 4310bf7c1c5SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 4320bf7c1c5SMatthew G. Knepley PetscObject obj; 4330bf7c1c5SMatthew G. Knepley PetscClassId id; 4340bf7c1c5SMatthew G. Knepley PetscInt Nc; 4350bf7c1c5SMatthew G. Knepley 4360bf7c1c5SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 4370bf7c1c5SMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 4380bf7c1c5SMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 4390bf7c1c5SMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 4400bf7c1c5SMatthew G. Knepley totNc += Nc; 4410bf7c1c5SMatthew G. Knepley } 4420643ed39SMatthew G. Knepley /* count non-zeros */ 4439566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(dmc)); 44483c47955SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 4450bf7c1c5SMatthew G. Knepley PetscObject obj; 4460bf7c1c5SMatthew G. Knepley PetscClassId id; 4470bf7c1c5SMatthew G. Knepley PetscInt Nc; 4480bf7c1c5SMatthew G. Knepley 4490bf7c1c5SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 4500bf7c1c5SMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 4510bf7c1c5SMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 4520bf7c1c5SMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 4530bf7c1c5SMatthew G. Knepley 45483c47955SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 4550643ed39SMatthew G. Knepley PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */ 45683c47955SMatthew G. Knepley PetscInt numFIndices, numCIndices; 45783c47955SMatthew G. Knepley 4589566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 4599566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 460fc7c92abSMatthew G. Knepley maxC = PetscMax(maxC, numCIndices); 46183c47955SMatthew G. Knepley { 462e8f14785SLisandro Dalcin PetscHashIJKey key; 463e8f14785SLisandro Dalcin PetscBool missing; 4640bf7c1c5SMatthew G. Knepley for (PetscInt i = 0; i < numFIndices; ++i) { 465adb2528bSMark Adams key.j = findices[i]; /* global column (from Plex) */ 466adb2528bSMark Adams if (key.j >= 0) { 46783c47955SMatthew G. Knepley /* Get indices for coarse elements */ 4680bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) { 4690bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 4700bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle here 4710bf7c1c5SMatthew G. Knepley key.i = cindices[j] * totNc + c + rStart; /* global cols (from Swarm) */ 472adb2528bSMark Adams if (key.i < 0) continue; 4739566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(ht, key, &missing)); 47483c47955SMatthew G. Knepley if (missing) { 4750643ed39SMatthew G. Knepley if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart]; 476e8f14785SLisandro Dalcin else ++onz[key.i - rStart]; 47763a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j); 47883c47955SMatthew G. Knepley } 479fc7c92abSMatthew G. Knepley } 480fc7c92abSMatthew G. Knepley } 4810bf7c1c5SMatthew G. Knepley } 482fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 48383c47955SMatthew G. Knepley } 4849566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 48583c47955SMatthew G. Knepley } 48683c47955SMatthew G. Knepley } 4879566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&ht)); 4889566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL)); 4899566063dSJacob Faibussowitsch PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 4909566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnz, onz)); 4910bf7c1c5SMatthew G. Knepley PetscCall(PetscMalloc3(maxC * totNc * totDim, &elemMat, maxC * totNc, &rowIDXs, maxC * dim, &xi)); 49283c47955SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 493ef0bb6c7SMatthew G. Knepley PetscTabulation Tcoarse; 49483c47955SMatthew G. Knepley PetscObject obj; 495ad9634fcSMatthew G. Knepley PetscClassId id; 496ea7032a0SMatthew G. Knepley PetscReal *fieldVals; 497d52c2f21SMatthew G. Knepley PetscInt Nc, bs; 49883c47955SMatthew G. Knepley 4999566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 500ad9634fcSMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 501ad9634fcSMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 502ad9634fcSMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 503ea7032a0SMatthew G. Knepley 504d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(dmc, coordname, &bs, NULL, (void **)&fieldVals)); 50583c47955SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 50683c47955SMatthew G. Knepley PetscInt *findices, *cindices; 50783c47955SMatthew G. Knepley PetscInt numFIndices, numCIndices; 50883c47955SMatthew G. Knepley 5090643ed39SMatthew G. Knepley /* TODO: Use DMField instead of assuming affine */ 5109566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ)); 5119566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 5129566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 513d52c2f21SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &fieldVals[cindices[j] * bs], &xi[j * dim]); 514ad9634fcSMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse)); 515ad9634fcSMatthew G. Knepley else PetscCall(PetscFVCreateTabulation((PetscFV)obj, 1, numCIndices, xi, 0, &Tcoarse)); 51683c47955SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 5170bf7c1c5SMatthew G. Knepley PetscCall(PetscArrayzero(elemMat, numCIndices * Nc * totDim)); 5180bf7c1c5SMatthew G. Knepley for (PetscInt i = 0; i < numFIndices / Nc; ++i) { 5190bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) { 5200bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 5210bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle and field here 5220643ed39SMatthew G. Knepley /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */ 5230bf7c1c5SMatthew G. Knepley elemMat[(j * totNc + c) * numFIndices + i * Nc + c] += Tcoarse->T[0][(j * numFIndices + i * Nc + c) * Nc + c] * (useDeltaFunction ? 1.0 : detJ); 52483c47955SMatthew G. Knepley } 5250643ed39SMatthew G. Knepley } 5260643ed39SMatthew G. Knepley } 5270bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) 5280bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle here 5290bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) rowIDXs[j * Nc + c] = cindices[j] * totNc + c + rStart; 5300bf7c1c5SMatthew G. Knepley if (0) PetscCall(DMPrintCellMatrix(cell, name, numCIndices * Nc, numFIndices, elemMat)); 5310bf7c1c5SMatthew G. Knepley PetscCall(MatSetValues(mass, numCIndices * Nc, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES)); 532fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 5339566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 5349566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tcoarse)); 53583c47955SMatthew G. Knepley } 536d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dmc, coordname, &bs, NULL, (void **)&fieldVals)); 53783c47955SMatthew G. Knepley } 5389566063dSJacob Faibussowitsch PetscCall(PetscFree3(elemMat, rowIDXs, xi)); 5399566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(dmc)); 5409566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ)); 5419566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY)); 5429566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY)); 5433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54483c47955SMatthew G. Knepley } 54583c47955SMatthew G. Knepley 546d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */ 547d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m) 548d71ae5a4SJacob Faibussowitsch { 549d0c080abSJoseph Pusztay Vec field; 550d0c080abSJoseph Pusztay PetscInt size; 551d0c080abSJoseph Pusztay 552d0c080abSJoseph Pusztay PetscFunctionBegin; 5539566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(sw, &field)); 5549566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(field, &size)); 5559566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(sw, &field)); 5569566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, m)); 5579566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*m)); 5589566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size)); 5599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL)); 5609566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*m)); 5619566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY)); 5629566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY)); 5639566063dSJacob Faibussowitsch PetscCall(MatShift(*m, 1.0)); 5649566063dSJacob Faibussowitsch PetscCall(MatSetDM(*m, sw)); 5653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 566d0c080abSJoseph Pusztay } 567d0c080abSJoseph Pusztay 568adb2528bSMark Adams /* FEM cols, Particle rows */ 569d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass) 570d71ae5a4SJacob Faibussowitsch { 571d52c2f21SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dmCoarse->data; 572895a1698SMatthew G. Knepley PetscSection gsf; 573d52c2f21SMatthew G. Knepley PetscInt m, n, Np; 57483c47955SMatthew G. Knepley void *ctx; 57583c47955SMatthew G. Knepley 57683c47955SMatthew G. Knepley PetscFunctionBegin; 577d52c2f21SMatthew G. Knepley PetscCheck(swarm->vec_field_num, PetscObjectComm((PetscObject)dmCoarse), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField(s) first"); 5789566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 5799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 5800bf7c1c5SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(dmCoarse, &Np)); 581d52c2f21SMatthew G. Knepley n = Np * swarm->vec_field_bs; 5829566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 5839566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE)); 5849566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 5859566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 58683c47955SMatthew G. Knepley 5879566063dSJacob Faibussowitsch PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx)); 5889566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 5893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 59083c47955SMatthew G. Knepley } 59183c47955SMatthew G. Knepley 592d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) 593d71ae5a4SJacob Faibussowitsch { 5944cc7f7b2SMatthew G. Knepley const char *name = "Mass Matrix Square"; 5954cc7f7b2SMatthew G. Knepley MPI_Comm comm; 5964cc7f7b2SMatthew G. Knepley PetscDS prob; 5974cc7f7b2SMatthew G. Knepley PetscSection fsection, globalFSection; 5984cc7f7b2SMatthew G. Knepley PetscHSetIJ ht; 5994cc7f7b2SMatthew G. Knepley PetscLayout rLayout, colLayout; 6004cc7f7b2SMatthew G. Knepley PetscInt *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize; 6014cc7f7b2SMatthew G. Knepley PetscInt locRows, locCols, rStart, colStart, colEnd, *rowIDXs; 6024cc7f7b2SMatthew G. Knepley PetscReal *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0}; 6034cc7f7b2SMatthew G. Knepley PetscScalar *elemMat, *elemMatSq; 6044cc7f7b2SMatthew G. Knepley PetscInt cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0; 605d52c2f21SMatthew G. Knepley const char *coordname; 6064cc7f7b2SMatthew G. Knepley 6074cc7f7b2SMatthew G. Knepley PetscFunctionBegin; 6089566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mass, &comm)); 6099566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmf, &cdim)); 6109566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmf, &prob)); 6119566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 6129566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim)); 6139566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ)); 6149566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection)); 6159566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 6169566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd)); 6179566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mass, &locRows, &locCols)); 6184cc7f7b2SMatthew G. Knepley 619d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetCoordinateField(dmc, &coordname)); 620d52c2f21SMatthew G. Knepley 6219566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &colLayout)); 6229566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(colLayout, locCols)); 6239566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(colLayout, 1)); 6249566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colLayout)); 6259566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd)); 6269566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&colLayout)); 6274cc7f7b2SMatthew G. Knepley 6289566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 6299566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 6309566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 6319566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 6329566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL)); 6339566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 6344cc7f7b2SMatthew G. Knepley 6359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmf, &depth)); 6369566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize)); 6374cc7f7b2SMatthew G. Knepley maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth); 6389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxAdjSize, &adj)); 6394cc7f7b2SMatthew G. Knepley 6409566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz)); 6419566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&ht)); 6424cc7f7b2SMatthew G. Knepley /* Count nonzeros 6434cc7f7b2SMatthew G. Knepley This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous 6444cc7f7b2SMatthew G. Knepley */ 6459566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(dmc)); 6464cc7f7b2SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 6474cc7f7b2SMatthew G. Knepley PetscInt i; 6484cc7f7b2SMatthew G. Knepley PetscInt *cindices; 6494cc7f7b2SMatthew G. Knepley PetscInt numCIndices; 6504cc7f7b2SMatthew G. Knepley #if 0 6514cc7f7b2SMatthew G. Knepley PetscInt adjSize = maxAdjSize, a, j; 6524cc7f7b2SMatthew G. Knepley #endif 6534cc7f7b2SMatthew G. Knepley 6549566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 6554cc7f7b2SMatthew G. Knepley maxC = PetscMax(maxC, numCIndices); 6564cc7f7b2SMatthew G. Knepley /* Diagonal block */ 657ad540459SPierre Jolivet for (i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices; 6584cc7f7b2SMatthew G. Knepley #if 0 6594cc7f7b2SMatthew G. Knepley /* Off-diagonal blocks */ 6609566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj)); 6614cc7f7b2SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 6624cc7f7b2SMatthew G. Knepley if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) { 6634cc7f7b2SMatthew G. Knepley const PetscInt ncell = adj[a]; 6644cc7f7b2SMatthew G. Knepley PetscInt *ncindices; 6654cc7f7b2SMatthew G. Knepley PetscInt numNCIndices; 6664cc7f7b2SMatthew G. Knepley 6679566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices)); 6684cc7f7b2SMatthew G. Knepley { 6694cc7f7b2SMatthew G. Knepley PetscHashIJKey key; 6704cc7f7b2SMatthew G. Knepley PetscBool missing; 6714cc7f7b2SMatthew G. Knepley 6724cc7f7b2SMatthew G. Knepley for (i = 0; i < numCIndices; ++i) { 6734cc7f7b2SMatthew G. Knepley key.i = cindices[i] + rStart; /* global rows (from Swarm) */ 6744cc7f7b2SMatthew G. Knepley if (key.i < 0) continue; 6754cc7f7b2SMatthew G. Knepley for (j = 0; j < numNCIndices; ++j) { 6764cc7f7b2SMatthew G. Knepley key.j = ncindices[j] + rStart; /* global column (from Swarm) */ 6774cc7f7b2SMatthew G. Knepley if (key.j < 0) continue; 6789566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(ht, key, &missing)); 6794cc7f7b2SMatthew G. Knepley if (missing) { 6804cc7f7b2SMatthew G. Knepley if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart]; 6814cc7f7b2SMatthew G. Knepley else ++onz[key.i - rStart]; 6824cc7f7b2SMatthew G. Knepley } 6834cc7f7b2SMatthew G. Knepley } 6844cc7f7b2SMatthew G. Knepley } 6854cc7f7b2SMatthew G. Knepley } 686fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, ncell, &numNCIndices, &ncindices)); 6874cc7f7b2SMatthew G. Knepley } 6884cc7f7b2SMatthew G. Knepley } 6894cc7f7b2SMatthew G. Knepley #endif 690fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 6914cc7f7b2SMatthew G. Knepley } 6929566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&ht)); 6939566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL)); 6949566063dSJacob Faibussowitsch PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 6959566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnz, onz)); 6969566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi)); 6974cc7f7b2SMatthew G. Knepley /* Fill in values 6984cc7f7b2SMatthew G. Knepley Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q) 6994cc7f7b2SMatthew G. Knepley Start just by producing block diagonal 7004cc7f7b2SMatthew G. Knepley Could loop over adjacent cells 7014cc7f7b2SMatthew G. Knepley Produce neighboring element matrix 7024cc7f7b2SMatthew G. Knepley TODO Determine which columns and rows correspond to shared dual vector 7034cc7f7b2SMatthew G. Knepley Do MatMatMult with rectangular matrices 7044cc7f7b2SMatthew G. Knepley Insert block 7054cc7f7b2SMatthew G. Knepley */ 7064cc7f7b2SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 7074cc7f7b2SMatthew G. Knepley PetscTabulation Tcoarse; 7084cc7f7b2SMatthew G. Knepley PetscObject obj; 7094cc7f7b2SMatthew G. Knepley PetscReal *coords; 7104cc7f7b2SMatthew G. Knepley PetscInt Nc, i; 7114cc7f7b2SMatthew G. Knepley 7129566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 7139566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 71463a3b9bcSJacob Faibussowitsch PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc); 715d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(dmc, coordname, NULL, NULL, (void **)&coords)); 7164cc7f7b2SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 7174cc7f7b2SMatthew G. Knepley PetscInt *findices, *cindices; 7184cc7f7b2SMatthew G. Knepley PetscInt numFIndices, numCIndices; 7194cc7f7b2SMatthew G. Knepley PetscInt p, c; 7204cc7f7b2SMatthew G. Knepley 7214cc7f7b2SMatthew G. Knepley /* TODO: Use DMField instead of assuming affine */ 7229566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ)); 7239566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 7249566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 725ad540459SPierre Jolivet for (p = 0; p < numCIndices; ++p) CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p] * cdim], &xi[p * cdim]); 7269566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse)); 7274cc7f7b2SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 7289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, numCIndices * totDim)); 7294cc7f7b2SMatthew G. Knepley for (i = 0; i < numFIndices; ++i) { 7304cc7f7b2SMatthew G. Knepley for (p = 0; p < numCIndices; ++p) { 7314cc7f7b2SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 7324cc7f7b2SMatthew G. Knepley /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */ 7334cc7f7b2SMatthew G. Knepley elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ); 7344cc7f7b2SMatthew G. Knepley } 7354cc7f7b2SMatthew G. Knepley } 7364cc7f7b2SMatthew G. Knepley } 7379566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tcoarse)); 7384cc7f7b2SMatthew G. Knepley for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart; 7399566063dSJacob Faibussowitsch if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat)); 7404cc7f7b2SMatthew G. Knepley /* Block diagonal */ 74178884ca7SMatthew G. Knepley if (numCIndices) { 7424cc7f7b2SMatthew G. Knepley PetscBLASInt blasn, blask; 7434cc7f7b2SMatthew G. Knepley PetscScalar one = 1.0, zero = 0.0; 7444cc7f7b2SMatthew G. Knepley 7459566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(numCIndices, &blasn)); 7469566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(numFIndices, &blask)); 747792fecdfSBarry Smith PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn)); 7484cc7f7b2SMatthew G. Knepley } 7499566063dSJacob Faibussowitsch PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES)); 7504cf0e950SBarry Smith /* TODO off-diagonal */ 751fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(dmc, cell, &numCIndices, &cindices)); 7529566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 7534cc7f7b2SMatthew G. Knepley } 754d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dmc, coordname, NULL, NULL, (void **)&coords)); 7554cc7f7b2SMatthew G. Knepley } 7569566063dSJacob Faibussowitsch PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi)); 7579566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 7589566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(dmc)); 7599566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ)); 7609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY)); 7619566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY)); 7623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7634cc7f7b2SMatthew G. Knepley } 7644cc7f7b2SMatthew G. Knepley 765cc4c1da9SBarry Smith /*@ 7664cc7f7b2SMatthew G. Knepley DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p 7674cc7f7b2SMatthew G. Knepley 76820f4b53cSBarry Smith Collective 7694cc7f7b2SMatthew G. Knepley 77060225df5SJacob Faibussowitsch Input Parameters: 77120f4b53cSBarry Smith + dmCoarse - a `DMSWARM` 77220f4b53cSBarry Smith - dmFine - a `DMPLEX` 7734cc7f7b2SMatthew G. Knepley 77460225df5SJacob Faibussowitsch Output Parameter: 7754cc7f7b2SMatthew G. Knepley . mass - the square of the particle mass matrix 7764cc7f7b2SMatthew G. Knepley 7774cc7f7b2SMatthew G. Knepley Level: advanced 7784cc7f7b2SMatthew G. Knepley 77920f4b53cSBarry Smith Note: 7804cc7f7b2SMatthew G. Knepley We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the 7814cc7f7b2SMatthew G. Knepley future to compute the full normal equations. 7824cc7f7b2SMatthew G. Knepley 78320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMCreateMassMatrix()` 7844cc7f7b2SMatthew G. Knepley @*/ 785d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass) 786d71ae5a4SJacob Faibussowitsch { 7874cc7f7b2SMatthew G. Knepley PetscInt n; 7884cc7f7b2SMatthew G. Knepley void *ctx; 7894cc7f7b2SMatthew G. Knepley 7904cc7f7b2SMatthew G. Knepley PetscFunctionBegin; 7919566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dmCoarse, &n)); 7929566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 7939566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE)); 7949566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 7959566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 7964cc7f7b2SMatthew G. Knepley 7979566063dSJacob Faibussowitsch PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx)); 7989566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view")); 7993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8004cc7f7b2SMatthew G. Knepley } 8014cc7f7b2SMatthew G. Knepley 802cc4c1da9SBarry Smith /*@ 80320f4b53cSBarry Smith DMSwarmCreateGlobalVectorFromField - Creates a `Vec` object sharing the array associated with a given field 804d3a51819SDave May 80520f4b53cSBarry Smith Collective 806d3a51819SDave May 80760225df5SJacob Faibussowitsch Input Parameters: 80820f4b53cSBarry Smith + dm - a `DMSWARM` 80962741f57SDave May - fieldname - the textual name given to a registered field 810d3a51819SDave May 81160225df5SJacob Faibussowitsch Output Parameter: 812d3a51819SDave May . vec - the vector 813d3a51819SDave May 814d3a51819SDave May Level: beginner 815d3a51819SDave May 816cc4c1da9SBarry Smith Note: 81720f4b53cSBarry Smith The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromField()`. 8188b8a3813SDave May 81920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()` 820d3a51819SDave May @*/ 821d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) 822d71ae5a4SJacob Faibussowitsch { 823fb1bcc12SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 824b5bcf523SDave May 825fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 826ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 8279566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec)); 8283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 829b5bcf523SDave May } 830b5bcf523SDave May 831cc4c1da9SBarry Smith /*@ 83220f4b53cSBarry Smith DMSwarmDestroyGlobalVectorFromField - Destroys the `Vec` object which share the array associated with a given field 833d3a51819SDave May 83420f4b53cSBarry Smith Collective 835d3a51819SDave May 83660225df5SJacob Faibussowitsch Input Parameters: 83720f4b53cSBarry Smith + dm - a `DMSWARM` 83862741f57SDave May - fieldname - the textual name given to a registered field 839d3a51819SDave May 84060225df5SJacob Faibussowitsch Output Parameter: 841d3a51819SDave May . vec - the vector 842d3a51819SDave May 843d3a51819SDave May Level: beginner 844d3a51819SDave May 84520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()` 846d3a51819SDave May @*/ 847d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) 848d71ae5a4SJacob Faibussowitsch { 849fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 850ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 8519566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec)); 8523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 853b5bcf523SDave May } 854b5bcf523SDave May 855cc4c1da9SBarry Smith /*@ 85620f4b53cSBarry Smith DMSwarmCreateLocalVectorFromField - Creates a `Vec` object sharing the array associated with a given field 857fb1bcc12SMatthew G. Knepley 85820f4b53cSBarry Smith Collective 859fb1bcc12SMatthew G. Knepley 86060225df5SJacob Faibussowitsch Input Parameters: 86120f4b53cSBarry Smith + dm - a `DMSWARM` 86262741f57SDave May - fieldname - the textual name given to a registered field 863fb1bcc12SMatthew G. Knepley 86460225df5SJacob Faibussowitsch Output Parameter: 865fb1bcc12SMatthew G. Knepley . vec - the vector 866fb1bcc12SMatthew G. Knepley 867fb1bcc12SMatthew G. Knepley Level: beginner 868fb1bcc12SMatthew G. Knepley 86920f4b53cSBarry Smith Note: 8708b8a3813SDave May The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField(). 8718b8a3813SDave May 87220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()` 873fb1bcc12SMatthew G. Knepley @*/ 874d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) 875d71ae5a4SJacob Faibussowitsch { 876fb1bcc12SMatthew G. Knepley MPI_Comm comm = PETSC_COMM_SELF; 877bbe8250bSMatthew G. Knepley 878fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 8799566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec)); 8803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 881bbe8250bSMatthew G. Knepley } 882fb1bcc12SMatthew G. Knepley 883cc4c1da9SBarry Smith /*@ 88420f4b53cSBarry Smith DMSwarmDestroyLocalVectorFromField - Destroys the `Vec` object which share the array associated with a given field 885fb1bcc12SMatthew G. Knepley 88620f4b53cSBarry Smith Collective 887fb1bcc12SMatthew G. Knepley 88860225df5SJacob Faibussowitsch Input Parameters: 88920f4b53cSBarry Smith + dm - a `DMSWARM` 89062741f57SDave May - fieldname - the textual name given to a registered field 891fb1bcc12SMatthew G. Knepley 89260225df5SJacob Faibussowitsch Output Parameter: 893fb1bcc12SMatthew G. Knepley . vec - the vector 894fb1bcc12SMatthew G. Knepley 895fb1bcc12SMatthew G. Knepley Level: beginner 896fb1bcc12SMatthew G. Knepley 89720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()` 898fb1bcc12SMatthew G. Knepley @*/ 899d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) 900d71ae5a4SJacob Faibussowitsch { 901fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 902ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 9039566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec)); 9043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 905bbe8250bSMatthew G. Knepley } 906bbe8250bSMatthew G. Knepley 907cc4c1da9SBarry Smith /*@ 90820f4b53cSBarry Smith DMSwarmInitializeFieldRegister - Initiates the registration of fields to a `DMSWARM` 909d3a51819SDave May 91020f4b53cSBarry Smith Collective 911d3a51819SDave May 91260225df5SJacob Faibussowitsch Input Parameter: 91320f4b53cSBarry Smith . dm - a `DMSWARM` 914d3a51819SDave May 915d3a51819SDave May Level: beginner 916d3a51819SDave May 91720f4b53cSBarry Smith Note: 91820f4b53cSBarry Smith After all fields have been registered, you must call `DMSwarmFinalizeFieldRegister()`. 919d3a51819SDave May 92020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`, 921db781477SPatrick Sanan `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 922d3a51819SDave May @*/ 923d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeFieldRegister(DM dm) 924d71ae5a4SJacob Faibussowitsch { 9255f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 9263454631fSDave May 927521f74f9SMatthew G. Knepley PetscFunctionBegin; 928cc651181SDave May if (!swarm->field_registration_initialized) { 9295f50eb2eSDave May swarm->field_registration_initialized = PETSC_TRUE; 930da81f932SPierre Jolivet PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifier */ 9319566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT)); /* used for communication */ 932cc651181SDave May } 9333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9345f50eb2eSDave May } 9355f50eb2eSDave May 93674d0cae8SMatthew G. Knepley /*@ 93720f4b53cSBarry Smith DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a `DMSWARM` 938d3a51819SDave May 93920f4b53cSBarry Smith Collective 940d3a51819SDave May 94160225df5SJacob Faibussowitsch Input Parameter: 94220f4b53cSBarry Smith . dm - a `DMSWARM` 943d3a51819SDave May 944d3a51819SDave May Level: beginner 945d3a51819SDave May 94620f4b53cSBarry Smith Note: 94720f4b53cSBarry Smith After `DMSwarmFinalizeFieldRegister()` has been called, no new fields can be defined on the `DMSWARM`. 948d3a51819SDave May 94920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`, 950db781477SPatrick Sanan `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 951d3a51819SDave May @*/ 952d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm) 953d71ae5a4SJacob Faibussowitsch { 9545f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 9556845f8f5SDave May 956521f74f9SMatthew G. Knepley PetscFunctionBegin; 95748a46eb9SPierre Jolivet if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db)); 958f0cdbbbaSDave May swarm->field_registration_finalized = PETSC_TRUE; 9593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9605f50eb2eSDave May } 9615f50eb2eSDave May 96274d0cae8SMatthew G. Knepley /*@ 96320f4b53cSBarry Smith DMSwarmSetLocalSizes - Sets the length of all registered fields on the `DMSWARM` 964d3a51819SDave May 96520f4b53cSBarry Smith Not Collective 966d3a51819SDave May 96760225df5SJacob Faibussowitsch Input Parameters: 96820f4b53cSBarry Smith + dm - a `DMSWARM` 969d3a51819SDave May . nlocal - the length of each registered field 97062741f57SDave May - buffer - the length of the buffer used to efficient dynamic re-sizing 971d3a51819SDave May 972d3a51819SDave May Level: beginner 973d3a51819SDave May 97420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()` 975d3a51819SDave May @*/ 976d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetLocalSizes(DM dm, PetscInt nlocal, PetscInt buffer) 977d71ae5a4SJacob Faibussowitsch { 9785f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 9795f50eb2eSDave May 980521f74f9SMatthew G. Knepley PetscFunctionBegin; 9819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0)); 9829566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer)); 9839566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0)); 9843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9855f50eb2eSDave May } 9865f50eb2eSDave May 98774d0cae8SMatthew G. Knepley /*@ 98820f4b53cSBarry Smith DMSwarmSetCellDM - Attaches a `DM` to a `DMSWARM` 989d3a51819SDave May 99020f4b53cSBarry Smith Collective 991d3a51819SDave May 99260225df5SJacob Faibussowitsch Input Parameters: 99320f4b53cSBarry Smith + dm - a `DMSWARM` 99420f4b53cSBarry Smith - dmcell - the `DM` to attach to the `DMSWARM` 995d3a51819SDave May 996d3a51819SDave May Level: beginner 997d3a51819SDave May 99820f4b53cSBarry Smith Note: 99920f4b53cSBarry Smith The attached `DM` (dmcell) will be queried for point location and 100020f4b53cSBarry Smith neighbor MPI-rank information if `DMSwarmMigrate()` is called. 1001d3a51819SDave May 100220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()` 1003d3a51819SDave May @*/ 1004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetCellDM(DM dm, DM dmcell) 1005d71ae5a4SJacob Faibussowitsch { 1006521f74f9SMatthew G. Knepley PetscFunctionBegin; 1007d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1008d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(dmcell, DM_CLASSID, 2); 1009d52c2f21SMatthew G. Knepley PetscCall(DMSwarmPushCellDM(dm, dmcell, 0, NULL, DMSwarmPICField_coor)); 10103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1011b16650c8SDave May } 1012b16650c8SDave May 101374d0cae8SMatthew G. Knepley /*@ 101420f4b53cSBarry Smith DMSwarmGetCellDM - Fetches the attached cell `DM` 1015d3a51819SDave May 101620f4b53cSBarry Smith Collective 1017d3a51819SDave May 101860225df5SJacob Faibussowitsch Input Parameter: 101920f4b53cSBarry Smith . dm - a `DMSWARM` 1020d3a51819SDave May 102160225df5SJacob Faibussowitsch Output Parameter: 102220f4b53cSBarry Smith . dmcell - the `DM` which was attached to the `DMSWARM` 1023d3a51819SDave May 1024d3a51819SDave May Level: beginner 1025d3a51819SDave May 102620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()` 1027d3a51819SDave May @*/ 1028d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetCellDM(DM dm, DM *dmcell) 1029d71ae5a4SJacob Faibussowitsch { 1030fe39f135SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1031521f74f9SMatthew G. Knepley 1032521f74f9SMatthew G. Knepley PetscFunctionBegin; 1033d52c2f21SMatthew G. Knepley *dmcell = swarm->cellinfo ? swarm->cellinfo[0].dm : NULL; 1034d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1035d52c2f21SMatthew G. Knepley } 1036d52c2f21SMatthew G. Knepley 1037d52c2f21SMatthew G. Knepley static PetscErrorCode CellDMInfoDestroy(CellDMInfo *info) 1038d52c2f21SMatthew G. Knepley { 1039d52c2f21SMatthew G. Knepley PetscFunctionBegin; 1040d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < (*info)->Nf; ++f) PetscCall(PetscFree((*info)->dmFields[f])); 1041d52c2f21SMatthew G. Knepley PetscCall(PetscFree((*info)->dmFields)); 1042d52c2f21SMatthew G. Knepley PetscCall(PetscFree((*info)->coordField)); 1043d52c2f21SMatthew G. Knepley PetscCall(DMDestroy(&(*info)->dm)); 1044d52c2f21SMatthew G. Knepley PetscCall(PetscFree(*info)); 1045d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1046d52c2f21SMatthew G. Knepley } 1047d52c2f21SMatthew G. Knepley 1048d52c2f21SMatthew G. Knepley /*@ 1049d52c2f21SMatthew G. Knepley DMSwarmPushCellDM - Attaches a `DM` to a `DMSWARM` 1050d52c2f21SMatthew G. Knepley 1051d52c2f21SMatthew G. Knepley Collective 1052d52c2f21SMatthew G. Knepley 1053d52c2f21SMatthew G. Knepley Input Parameters: 1054d52c2f21SMatthew G. Knepley + sw - a `DMSWARM` 1055d52c2f21SMatthew G. Knepley . dmcell - the `DM` to attach to the `DMSWARM` 1056d52c2f21SMatthew G. Knepley . Nf - the number of swarm fields defining the `DM` 1057d52c2f21SMatthew G. Knepley . dmFields - an array of field names for the fields defining the `DM` 1058d52c2f21SMatthew G. Knepley - coordField - the name for the swarm field to use for particle coordinates on the cell `DM` 1059d52c2f21SMatthew G. Knepley 1060d52c2f21SMatthew G. Knepley Level: beginner 1061d52c2f21SMatthew G. Knepley 1062d52c2f21SMatthew G. Knepley Note: 1063d52c2f21SMatthew G. Knepley The attached `DM` (dmcell) will be queried for point location and 1064d52c2f21SMatthew G. Knepley neighbor MPI-rank information if `DMSwarmMigrate()` is called. 1065d52c2f21SMatthew G. Knepley 1066d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmPopCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()` 1067d52c2f21SMatthew G. Knepley @*/ 1068d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmPushCellDM(DM sw, DM dmcell, PetscInt Nf, const char *dmFields[], const char coordField[]) 1069d52c2f21SMatthew G. Knepley { 1070d52c2f21SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1071d52c2f21SMatthew G. Knepley CellDMInfo info; 1072d52c2f21SMatthew G. Knepley PetscBool rebin = swarm->cellinfo ? PETSC_TRUE : PETSC_FALSE; 1073d52c2f21SMatthew G. Knepley 1074d52c2f21SMatthew G. Knepley PetscFunctionBegin; 1075d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 1076d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(dmcell, DM_CLASSID, 2); 1077d52c2f21SMatthew G. Knepley if (Nf) PetscAssertPointer(dmFields, 4); 1078d52c2f21SMatthew G. Knepley PetscAssertPointer(coordField, 5); 1079d52c2f21SMatthew G. Knepley PetscCall(PetscNew(&info)); 1080d52c2f21SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)dmcell)); 1081d52c2f21SMatthew G. Knepley info->dm = dmcell; 1082d52c2f21SMatthew G. Knepley info->Nf = Nf; 1083d52c2f21SMatthew G. Knepley info->next = swarm->cellinfo; 1084d52c2f21SMatthew G. Knepley swarm->cellinfo = info; 1085d52c2f21SMatthew G. Knepley // Define the DM fields 1086d52c2f21SMatthew G. Knepley PetscCall(PetscMalloc1(info->Nf, &info->dmFields)); 1087d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < info->Nf; ++f) PetscCall(PetscStrallocpy(dmFields[f], &info->dmFields[f])); 1088d52c2f21SMatthew G. Knepley if (info->Nf) PetscCall(DMSwarmVectorDefineFields(sw, info->Nf, (const char **)info->dmFields)); 1089d52c2f21SMatthew G. Knepley // Set the coordinate field 1090d52c2f21SMatthew G. Knepley PetscCall(PetscStrallocpy(coordField, &info->coordField)); 1091d52c2f21SMatthew G. Knepley if (info->coordField) PetscCall(DMSwarmSetCoordinateField(sw, info->coordField)); 1092d52c2f21SMatthew G. Knepley // Rebin the cells and set cell_id field 1093d52c2f21SMatthew G. Knepley if (rebin) PetscCall(DMSwarmMigrate(sw, PETSC_FALSE)); 1094d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1095d52c2f21SMatthew G. Knepley } 1096d52c2f21SMatthew G. Knepley 1097d52c2f21SMatthew G. Knepley /*@ 1098d52c2f21SMatthew G. Knepley DMSwarmPopCellDM - Discard the current cell `DM` and restore the previous one, if it exists 1099d52c2f21SMatthew G. Knepley 1100d52c2f21SMatthew G. Knepley Collective 1101d52c2f21SMatthew G. Knepley 1102d52c2f21SMatthew G. Knepley Input Parameter: 1103d52c2f21SMatthew G. Knepley . sw - a `DMSWARM` 1104d52c2f21SMatthew G. Knepley 1105d52c2f21SMatthew G. Knepley Level: beginner 1106d52c2f21SMatthew G. Knepley 1107d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmPushCellDM()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()` 1108d52c2f21SMatthew G. Knepley @*/ 1109d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmPopCellDM(DM sw) 1110d52c2f21SMatthew G. Knepley { 1111d52c2f21SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1112d52c2f21SMatthew G. Knepley CellDMInfo info = swarm->cellinfo; 1113d52c2f21SMatthew G. Knepley 1114d52c2f21SMatthew G. Knepley PetscFunctionBegin; 1115d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 1116d52c2f21SMatthew G. Knepley if (!swarm->cellinfo) PetscFunctionReturn(PETSC_SUCCESS); 1117d52c2f21SMatthew G. Knepley if (info->next) { 1118d52c2f21SMatthew G. Knepley CellDMInfo newinfo = info->next; 1119d52c2f21SMatthew G. Knepley 1120d52c2f21SMatthew G. Knepley swarm->cellinfo = info->next; 1121d52c2f21SMatthew G. Knepley // Define the DM fields 1122d52c2f21SMatthew G. Knepley PetscCall(DMSwarmVectorDefineFields(sw, newinfo->Nf, (const char **)newinfo->dmFields)); 1123d52c2f21SMatthew G. Knepley // Set the coordinate field 1124d52c2f21SMatthew G. Knepley PetscCall(DMSwarmSetCoordinateField(sw, newinfo->coordField)); 1125d52c2f21SMatthew G. Knepley // Rebin the cells and set cell_id field 1126d52c2f21SMatthew G. Knepley PetscCall(DMSwarmMigrate(sw, PETSC_FALSE)); 1127d52c2f21SMatthew G. Knepley } 1128d52c2f21SMatthew G. Knepley PetscCall(CellDMInfoDestroy(&info)); 11293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1130fe39f135SDave May } 1131fe39f135SDave May 113274d0cae8SMatthew G. Knepley /*@ 1133d5b43468SJose E. Roman DMSwarmGetLocalSize - Retrieves the local length of fields registered 1134d3a51819SDave May 113520f4b53cSBarry Smith Not Collective 1136d3a51819SDave May 113760225df5SJacob Faibussowitsch Input Parameter: 113820f4b53cSBarry Smith . dm - a `DMSWARM` 1139d3a51819SDave May 114060225df5SJacob Faibussowitsch Output Parameter: 1141d3a51819SDave May . nlocal - the length of each registered field 1142d3a51819SDave May 1143d3a51819SDave May Level: beginner 1144d3a51819SDave May 114520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()` 1146d3a51819SDave May @*/ 1147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal) 1148d71ae5a4SJacob Faibussowitsch { 1149dcf43ee8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1150dcf43ee8SDave May 1151521f74f9SMatthew G. Knepley PetscFunctionBegin; 11529566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL)); 11533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1154dcf43ee8SDave May } 1155dcf43ee8SDave May 115674d0cae8SMatthew G. Knepley /*@ 1157d5b43468SJose E. Roman DMSwarmGetSize - Retrieves the total length of fields registered 1158d3a51819SDave May 115920f4b53cSBarry Smith Collective 1160d3a51819SDave May 116160225df5SJacob Faibussowitsch Input Parameter: 116220f4b53cSBarry Smith . dm - a `DMSWARM` 1163d3a51819SDave May 116460225df5SJacob Faibussowitsch Output Parameter: 1165d3a51819SDave May . n - the total length of each registered field 1166d3a51819SDave May 1167d3a51819SDave May Level: beginner 1168d3a51819SDave May 1169d3a51819SDave May Note: 117020f4b53cSBarry Smith This calls `MPI_Allreduce()` upon each call (inefficient but safe) 1171d3a51819SDave May 117220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()` 1173d3a51819SDave May @*/ 1174d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n) 1175d71ae5a4SJacob Faibussowitsch { 1176dcf43ee8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 11775627991aSBarry Smith PetscInt nlocal; 1178dcf43ee8SDave May 1179521f74f9SMatthew G. Knepley PetscFunctionBegin; 11809566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL)); 1181462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 11823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1183dcf43ee8SDave May } 1184dcf43ee8SDave May 1185cc4c1da9SBarry Smith /*@ 118620f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField - Register a field to a `DMSWARM` with a native PETSc data type 1187d3a51819SDave May 118820f4b53cSBarry Smith Collective 1189d3a51819SDave May 119060225df5SJacob Faibussowitsch Input Parameters: 119120f4b53cSBarry Smith + dm - a `DMSWARM` 1192d3a51819SDave May . fieldname - the textual name to identify this field 1193d3a51819SDave May . blocksize - the number of each data type 119420f4b53cSBarry Smith - type - a valid PETSc data type (`PETSC_CHAR`, `PETSC_SHORT`, `PETSC_INT`, `PETSC_FLOAT`, `PETSC_REAL`, `PETSC_LONG`) 1195d3a51819SDave May 1196d3a51819SDave May Level: beginner 1197d3a51819SDave May 1198d3a51819SDave May Notes: 11998b8a3813SDave May The textual name for each registered field must be unique. 1200d3a51819SDave May 120120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 1202d3a51819SDave May @*/ 1203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type) 1204d71ae5a4SJacob Faibussowitsch { 1205b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1206b62e03f8SDave May size_t size; 1207b62e03f8SDave May 1208521f74f9SMatthew G. Knepley PetscFunctionBegin; 120928b400f6SJacob Faibussowitsch PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first"); 121028b400f6SJacob Faibussowitsch PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first"); 12115f50eb2eSDave May 121208401ef6SPierre Jolivet PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 121308401ef6SPierre Jolivet PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 121408401ef6SPierre Jolivet PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 121508401ef6SPierre Jolivet PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 121608401ef6SPierre Jolivet PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 1217b62e03f8SDave May 12189566063dSJacob Faibussowitsch PetscCall(PetscDataTypeGetSize(type, &size)); 1219b62e03f8SDave May /* Load a specific data type into data bucket, specifying textual name and its size in bytes */ 12209566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL)); 122152c3ed93SDave May { 122277048351SPatrick Sanan DMSwarmDataField gfield; 122352c3ed93SDave May 12249566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 12259566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize)); 122652c3ed93SDave May } 1227b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = type; 12283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1229b62e03f8SDave May } 1230b62e03f8SDave May 1231d3a51819SDave May /*@C 123220f4b53cSBarry Smith DMSwarmRegisterUserStructField - Register a user defined struct to a `DMSWARM` 1233d3a51819SDave May 123420f4b53cSBarry Smith Collective 1235d3a51819SDave May 123660225df5SJacob Faibussowitsch Input Parameters: 123720f4b53cSBarry Smith + dm - a `DMSWARM` 1238d3a51819SDave May . fieldname - the textual name to identify this field 123962741f57SDave May - size - the size in bytes of the user struct of each data type 1240d3a51819SDave May 1241d3a51819SDave May Level: beginner 1242d3a51819SDave May 124320f4b53cSBarry Smith Note: 12448b8a3813SDave May The textual name for each registered field must be unique. 1245d3a51819SDave May 124620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()` 1247d3a51819SDave May @*/ 1248d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size) 1249d71ae5a4SJacob Faibussowitsch { 1250b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1251b62e03f8SDave May 1252521f74f9SMatthew G. Knepley PetscFunctionBegin; 12539566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL)); 1254b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT; 12553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1256b62e03f8SDave May } 1257b62e03f8SDave May 1258d3a51819SDave May /*@C 125920f4b53cSBarry Smith DMSwarmRegisterUserDatatypeField - Register a user defined data type to a `DMSWARM` 1260d3a51819SDave May 126120f4b53cSBarry Smith Collective 1262d3a51819SDave May 126360225df5SJacob Faibussowitsch Input Parameters: 126420f4b53cSBarry Smith + dm - a `DMSWARM` 1265d3a51819SDave May . fieldname - the textual name to identify this field 1266d3a51819SDave May . size - the size in bytes of the user data type 126762741f57SDave May - blocksize - the number of each data type 1268d3a51819SDave May 1269d3a51819SDave May Level: beginner 1270d3a51819SDave May 127120f4b53cSBarry Smith Note: 12728b8a3813SDave May The textual name for each registered field must be unique. 1273d3a51819SDave May 127442747ad1SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()` 1275d3a51819SDave May @*/ 1276d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize) 1277d71ae5a4SJacob Faibussowitsch { 1278b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1279b62e03f8SDave May 1280521f74f9SMatthew G. Knepley PetscFunctionBegin; 12819566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL)); 1282320740a0SDave May { 128377048351SPatrick Sanan DMSwarmDataField gfield; 1284320740a0SDave May 12859566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 12869566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize)); 1287320740a0SDave May } 1288b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN; 12893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1290b62e03f8SDave May } 1291b62e03f8SDave May 1292d3a51819SDave May /*@C 1293d3a51819SDave May DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field 1294d3a51819SDave May 1295cc4c1da9SBarry Smith Not Collective, No Fortran Support 1296d3a51819SDave May 129760225df5SJacob Faibussowitsch Input Parameters: 129820f4b53cSBarry Smith + dm - a `DMSWARM` 129962741f57SDave May - fieldname - the textual name to identify this field 1300d3a51819SDave May 130160225df5SJacob Faibussowitsch Output Parameters: 130262741f57SDave May + blocksize - the number of each data type 1303d3a51819SDave May . type - the data type 130462741f57SDave May - data - pointer to raw array 1305d3a51819SDave May 1306d3a51819SDave May Level: beginner 1307d3a51819SDave May 1308d3a51819SDave May Notes: 130920f4b53cSBarry Smith The array must be returned using a matching call to `DMSwarmRestoreField()`. 1310d3a51819SDave May 131120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreField()` 1312d3a51819SDave May @*/ 1313d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) 1314d71ae5a4SJacob Faibussowitsch { 1315b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 131677048351SPatrick Sanan DMSwarmDataField gfield; 1317b62e03f8SDave May 1318521f74f9SMatthew G. Knepley PetscFunctionBegin; 1319ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 13209566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 13219566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 13229566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldGetAccess(gfield)); 13239566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldGetEntries(gfield, data)); 1324ad540459SPierre Jolivet if (blocksize) *blocksize = gfield->bs; 1325ad540459SPierre Jolivet if (type) *type = gfield->petsc_type; 13263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1327b62e03f8SDave May } 1328b62e03f8SDave May 1329d3a51819SDave May /*@C 1330d3a51819SDave May DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field 1331d3a51819SDave May 1332cc4c1da9SBarry Smith Not Collective, No Fortran Support 1333d3a51819SDave May 133460225df5SJacob Faibussowitsch Input Parameters: 133520f4b53cSBarry Smith + dm - a `DMSWARM` 133662741f57SDave May - fieldname - the textual name to identify this field 1337d3a51819SDave May 133860225df5SJacob Faibussowitsch Output Parameters: 133962741f57SDave May + blocksize - the number of each data type 1340d3a51819SDave May . type - the data type 134162741f57SDave May - data - pointer to raw array 1342d3a51819SDave May 1343d3a51819SDave May Level: beginner 1344d3a51819SDave May 1345d3a51819SDave May Notes: 134620f4b53cSBarry Smith The user must call `DMSwarmGetField()` prior to calling `DMSwarmRestoreField()`. 1347d3a51819SDave May 134820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetField()` 1349d3a51819SDave May @*/ 1350d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) 1351d71ae5a4SJacob Faibussowitsch { 1352b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 135377048351SPatrick Sanan DMSwarmDataField gfield; 1354b62e03f8SDave May 1355521f74f9SMatthew G. Knepley PetscFunctionBegin; 1356ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 13579566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 13589566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldRestoreAccess(gfield)); 1359b62e03f8SDave May if (data) *data = NULL; 13603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1361b62e03f8SDave May } 1362b62e03f8SDave May 1363d52c2f21SMatthew G. Knepley /*@ 1364d52c2f21SMatthew G. Knepley DMSwarmGetCoordinateField - Get the name of the field holding particle coordinates 1365d52c2f21SMatthew G. Knepley 1366d52c2f21SMatthew G. Knepley Not Collective 1367d52c2f21SMatthew G. Knepley 1368d52c2f21SMatthew G. Knepley Input Parameter: 1369d52c2f21SMatthew G. Knepley . sw - a `DMSWARM` 1370d52c2f21SMatthew G. Knepley 1371d52c2f21SMatthew G. Knepley Output Parameter: 1372d52c2f21SMatthew G. Knepley . fieldname - the name of the coordinate field 1373d52c2f21SMatthew G. Knepley 1374d52c2f21SMatthew G. Knepley Level: intermediate 1375d52c2f21SMatthew G. Knepley 1376d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmSetCoordinateField()`, `DMSwarmGetField()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()` 1377d52c2f21SMatthew G. Knepley @*/ 1378d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmGetCoordinateField(DM sw, const char *fieldname[]) 1379d52c2f21SMatthew G. Knepley { 1380d52c2f21SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1381d52c2f21SMatthew G. Knepley 1382d52c2f21SMatthew G. Knepley PetscFunctionBegin; 1383d52c2f21SMatthew G. Knepley PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM); 1384d52c2f21SMatthew G. Knepley PetscAssertPointer(fieldname, 2); 1385d52c2f21SMatthew G. Knepley *fieldname = swarm->coord_name; 1386d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1387d52c2f21SMatthew G. Knepley } 1388d52c2f21SMatthew G. Knepley 1389d52c2f21SMatthew G. Knepley /*@ 1390d52c2f21SMatthew G. Knepley DMSwarmSetCoordinateField - Set the name of the field holding particle coordinates 1391d52c2f21SMatthew G. Knepley 1392d52c2f21SMatthew G. Knepley Not Collective 1393d52c2f21SMatthew G. Knepley 1394d52c2f21SMatthew G. Knepley Input Parameters: 1395d52c2f21SMatthew G. Knepley + sw - a `DMSWARM` 1396d52c2f21SMatthew G. Knepley - fieldname - the name of the coordinate field 1397d52c2f21SMatthew G. Knepley 1398d52c2f21SMatthew G. Knepley Level: intermediate 1399d52c2f21SMatthew G. Knepley 1400d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmGetCoordinateField()`, `DMSwarmGetField()`, `DMSwarmSetCellDM()`, `DMSwarmMigrate()` 1401d52c2f21SMatthew G. Knepley @*/ 1402d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmSetCoordinateField(DM sw, const char fieldname[]) 1403d52c2f21SMatthew G. Knepley { 1404d52c2f21SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 1405d52c2f21SMatthew G. Knepley 1406d52c2f21SMatthew G. Knepley PetscFunctionBegin; 1407d52c2f21SMatthew G. Knepley PetscValidHeaderSpecificType(sw, DM_CLASSID, 1, DMSWARM); 1408d52c2f21SMatthew G. Knepley PetscAssertPointer(fieldname, 2); 1409d52c2f21SMatthew G. Knepley PetscCall(PetscFree(swarm->coord_name)); 1410d52c2f21SMatthew G. Knepley PetscCall(PetscStrallocpy(fieldname, (char **)&swarm->coord_name)); 1411d52c2f21SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1412d52c2f21SMatthew G. Knepley } 1413d52c2f21SMatthew G. Knepley 14140bf7c1c5SMatthew G. Knepley PetscErrorCode DMSwarmGetFieldInfo(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type) 14150bf7c1c5SMatthew G. Knepley { 14160bf7c1c5SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 14170bf7c1c5SMatthew G. Knepley DMSwarmDataField gfield; 14180bf7c1c5SMatthew G. Knepley 14190bf7c1c5SMatthew G. Knepley PetscFunctionBegin; 14200bf7c1c5SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 14210bf7c1c5SMatthew G. Knepley PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 14220bf7c1c5SMatthew G. Knepley if (blocksize) *blocksize = gfield->bs; 14230bf7c1c5SMatthew G. Knepley if (type) *type = gfield->petsc_type; 14240bf7c1c5SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 14250bf7c1c5SMatthew G. Knepley } 14260bf7c1c5SMatthew G. Knepley 142774d0cae8SMatthew G. Knepley /*@ 142820f4b53cSBarry Smith DMSwarmAddPoint - Add space for one new point in the `DMSWARM` 1429d3a51819SDave May 143020f4b53cSBarry Smith Not Collective 1431d3a51819SDave May 143260225df5SJacob Faibussowitsch Input Parameter: 143320f4b53cSBarry Smith . dm - a `DMSWARM` 1434d3a51819SDave May 1435d3a51819SDave May Level: beginner 1436d3a51819SDave May 1437d3a51819SDave May Notes: 14388b8a3813SDave May The new point will have all fields initialized to zero. 1439d3a51819SDave May 144020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddNPoints()` 1441d3a51819SDave May @*/ 1442d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddPoint(DM dm) 1443d71ae5a4SJacob Faibussowitsch { 1444cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1445cb1d1399SDave May 1446521f74f9SMatthew G. Knepley PetscFunctionBegin; 14479566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 14489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0)); 14499566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketAddPoint(swarm->db)); 14509566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0)); 14513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1452cb1d1399SDave May } 1453cb1d1399SDave May 145474d0cae8SMatthew G. Knepley /*@ 145520f4b53cSBarry Smith DMSwarmAddNPoints - Add space for a number of new points in the `DMSWARM` 1456d3a51819SDave May 145720f4b53cSBarry Smith Not Collective 1458d3a51819SDave May 145960225df5SJacob Faibussowitsch Input Parameters: 146020f4b53cSBarry Smith + dm - a `DMSWARM` 146162741f57SDave May - npoints - the number of new points to add 1462d3a51819SDave May 1463d3a51819SDave May Level: beginner 1464d3a51819SDave May 1465d3a51819SDave May Notes: 14668b8a3813SDave May The new point will have all fields initialized to zero. 1467d3a51819SDave May 146820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddPoint()` 1469d3a51819SDave May @*/ 1470d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints) 1471d71ae5a4SJacob Faibussowitsch { 1472cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1473cb1d1399SDave May PetscInt nlocal; 1474cb1d1399SDave May 1475521f74f9SMatthew G. Knepley PetscFunctionBegin; 14769566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0)); 14779566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL)); 1478cb1d1399SDave May nlocal = nlocal + npoints; 14799566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT)); 14809566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0)); 14813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1482cb1d1399SDave May } 1483cb1d1399SDave May 148474d0cae8SMatthew G. Knepley /*@ 148520f4b53cSBarry Smith DMSwarmRemovePoint - Remove the last point from the `DMSWARM` 1486d3a51819SDave May 148720f4b53cSBarry Smith Not Collective 1488d3a51819SDave May 148960225df5SJacob Faibussowitsch Input Parameter: 149020f4b53cSBarry Smith . dm - a `DMSWARM` 1491d3a51819SDave May 1492d3a51819SDave May Level: beginner 1493d3a51819SDave May 149420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePointAtIndex()` 1495d3a51819SDave May @*/ 1496d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePoint(DM dm) 1497d71ae5a4SJacob Faibussowitsch { 1498cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1499cb1d1399SDave May 1500521f74f9SMatthew G. Knepley PetscFunctionBegin; 15019566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0)); 15029566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRemovePoint(swarm->db)); 15039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0)); 15043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1505cb1d1399SDave May } 1506cb1d1399SDave May 150774d0cae8SMatthew G. Knepley /*@ 150820f4b53cSBarry Smith DMSwarmRemovePointAtIndex - Removes a specific point from the `DMSWARM` 1509d3a51819SDave May 151020f4b53cSBarry Smith Not Collective 1511d3a51819SDave May 151260225df5SJacob Faibussowitsch Input Parameters: 151320f4b53cSBarry Smith + dm - a `DMSWARM` 151462741f57SDave May - idx - index of point to remove 1515d3a51819SDave May 1516d3a51819SDave May Level: beginner 1517d3a51819SDave May 151820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()` 1519d3a51819SDave May @*/ 1520d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx) 1521d71ae5a4SJacob Faibussowitsch { 1522cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1523cb1d1399SDave May 1524521f74f9SMatthew G. Knepley PetscFunctionBegin; 15259566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0)); 15269566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx)); 15279566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0)); 15283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1529cb1d1399SDave May } 1530b62e03f8SDave May 153174d0cae8SMatthew G. Knepley /*@ 153220f4b53cSBarry Smith DMSwarmCopyPoint - Copy point pj to point pi in the `DMSWARM` 1533ba4fc9c6SDave May 153420f4b53cSBarry Smith Not Collective 1535ba4fc9c6SDave May 153660225df5SJacob Faibussowitsch Input Parameters: 153720f4b53cSBarry Smith + dm - a `DMSWARM` 1538ba4fc9c6SDave May . pi - the index of the point to copy 1539ba4fc9c6SDave May - pj - the point index where the copy should be located 1540ba4fc9c6SDave May 1541ba4fc9c6SDave May Level: beginner 1542ba4fc9c6SDave May 154320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()` 1544ba4fc9c6SDave May @*/ 1545d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj) 1546d71ae5a4SJacob Faibussowitsch { 1547ba4fc9c6SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1548ba4fc9c6SDave May 1549ba4fc9c6SDave May PetscFunctionBegin; 15509566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 15519566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj)); 15523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1553ba4fc9c6SDave May } 1554ba4fc9c6SDave May 155566976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points) 1556d71ae5a4SJacob Faibussowitsch { 1557521f74f9SMatthew G. Knepley PetscFunctionBegin; 15589566063dSJacob Faibussowitsch PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points)); 15593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15603454631fSDave May } 15613454631fSDave May 156274d0cae8SMatthew G. Knepley /*@ 156320f4b53cSBarry Smith DMSwarmMigrate - Relocates points defined in the `DMSWARM` to other MPI-ranks 1564d3a51819SDave May 156520f4b53cSBarry Smith Collective 1566d3a51819SDave May 156760225df5SJacob Faibussowitsch Input Parameters: 156820f4b53cSBarry Smith + dm - the `DMSWARM` 156962741f57SDave May - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank 1570d3a51819SDave May 1571d3a51819SDave May Level: advanced 1572d3a51819SDave May 157320f4b53cSBarry Smith Notes: 157420f4b53cSBarry Smith The `DM` will be modified to accommodate received points. 157520f4b53cSBarry Smith If `remove_sent_points` is `PETSC_TRUE`, any points that were sent will be removed from the `DM`. 157620f4b53cSBarry Smith Different styles of migration are supported. See `DMSwarmSetMigrateType()`. 157720f4b53cSBarry Smith 157820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()` 1579d3a51819SDave May @*/ 1580d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points) 1581d71ae5a4SJacob Faibussowitsch { 1582f0cdbbbaSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1583f0cdbbbaSDave May 1584521f74f9SMatthew G. Knepley PetscFunctionBegin; 15859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0)); 1586f0cdbbbaSDave May switch (swarm->migrate_type) { 1587d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_BASIC: 1588d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points)); 1589d71ae5a4SJacob Faibussowitsch break; 1590d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_DMCELLNSCATTER: 1591d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points)); 1592d71ae5a4SJacob Faibussowitsch break; 1593d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_DMCELLEXACT: 1594d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented"); 1595d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_USER: 1596d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented"); 1597d71ae5a4SJacob Faibussowitsch default: 1598d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown"); 1599f0cdbbbaSDave May } 16009566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0)); 16019566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dm)); 16023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16033454631fSDave May } 16043454631fSDave May 1605f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize); 1606f0cdbbbaSDave May 1607d3a51819SDave May /* 1608d3a51819SDave May DMSwarmCollectViewCreate 1609d3a51819SDave May 1610d3a51819SDave May * Applies a collection method and gathers point neighbour points into dm 1611d3a51819SDave May 1612d3a51819SDave May Notes: 16138b8a3813SDave May Users should call DMSwarmCollectViewDestroy() after 1614d3a51819SDave May they have finished computations associated with the collected points 1615d3a51819SDave May */ 1616d3a51819SDave May 161774d0cae8SMatthew G. Knepley /*@ 1618d3a51819SDave May DMSwarmCollectViewCreate - Applies a collection method and gathers points 161920f4b53cSBarry Smith in neighbour ranks into the `DMSWARM` 1620d3a51819SDave May 162120f4b53cSBarry Smith Collective 1622d3a51819SDave May 162360225df5SJacob Faibussowitsch Input Parameter: 162420f4b53cSBarry Smith . dm - the `DMSWARM` 1625d3a51819SDave May 1626d3a51819SDave May Level: advanced 1627d3a51819SDave May 162820f4b53cSBarry Smith Notes: 162920f4b53cSBarry Smith Users should call `DMSwarmCollectViewDestroy()` after 163020f4b53cSBarry Smith they have finished computations associated with the collected points 16310764c050SBarry Smith 163220f4b53cSBarry Smith Different collect methods are supported. See `DMSwarmSetCollectType()`. 163320f4b53cSBarry Smith 16340764c050SBarry Smith Developer Note: 16350764c050SBarry Smith Create and Destroy routines create new objects that can get destroyed, they do not change the state 16360764c050SBarry Smith of the current object. 16370764c050SBarry Smith 163820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()` 1639d3a51819SDave May @*/ 1640d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewCreate(DM dm) 1641d71ae5a4SJacob Faibussowitsch { 16422712d1f2SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 16432712d1f2SDave May PetscInt ng; 16442712d1f2SDave May 1645521f74f9SMatthew G. Knepley PetscFunctionBegin; 164628b400f6SJacob Faibussowitsch PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active"); 16479566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &ng)); 1648480eef7bSDave May switch (swarm->collect_type) { 1649d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_BASIC: 1650d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng)); 1651d71ae5a4SJacob Faibussowitsch break; 1652d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_DMDABOUNDINGBOX: 1653d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented"); 1654d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_GENERAL: 1655d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented"); 1656d71ae5a4SJacob Faibussowitsch default: 1657d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown"); 1658480eef7bSDave May } 1659480eef7bSDave May swarm->collect_view_active = PETSC_TRUE; 1660480eef7bSDave May swarm->collect_view_reset_nlocal = ng; 16613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16622712d1f2SDave May } 16632712d1f2SDave May 166474d0cae8SMatthew G. Knepley /*@ 166520f4b53cSBarry Smith DMSwarmCollectViewDestroy - Resets the `DMSWARM` to the size prior to calling `DMSwarmCollectViewCreate()` 1666d3a51819SDave May 166720f4b53cSBarry Smith Collective 1668d3a51819SDave May 166960225df5SJacob Faibussowitsch Input Parameters: 167020f4b53cSBarry Smith . dm - the `DMSWARM` 1671d3a51819SDave May 1672d3a51819SDave May Notes: 167320f4b53cSBarry Smith Users should call `DMSwarmCollectViewCreate()` before this function is called. 1674d3a51819SDave May 1675d3a51819SDave May Level: advanced 1676d3a51819SDave May 16770764c050SBarry Smith Developer Note: 16780764c050SBarry Smith Create and Destroy routines create new objects that can get destroyed, they do not change the state 16790764c050SBarry Smith of the current object. 16800764c050SBarry Smith 168120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()` 1682d3a51819SDave May @*/ 1683d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewDestroy(DM dm) 1684d71ae5a4SJacob Faibussowitsch { 16852712d1f2SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 16862712d1f2SDave May 1687521f74f9SMatthew G. Knepley PetscFunctionBegin; 168828b400f6SJacob Faibussowitsch PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active"); 16899566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1)); 1690480eef7bSDave May swarm->collect_view_active = PETSC_FALSE; 16913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16922712d1f2SDave May } 16933454631fSDave May 169466976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmSetUpPIC(DM dm) 1695d71ae5a4SJacob Faibussowitsch { 1696f0cdbbbaSDave May PetscInt dim; 1697f0cdbbbaSDave May 1698521f74f9SMatthew G. Knepley PetscFunctionBegin; 16999566063dSJacob Faibussowitsch PetscCall(DMSwarmSetNumSpecies(dm, 1)); 17009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 170163a3b9bcSJacob Faibussowitsch PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim); 170263a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim); 17039566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_coor, dim, PETSC_DOUBLE)); 17049566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_cellid, 1, PETSC_INT)); 1705d52c2f21SMatthew G. Knepley PetscCall(DMSwarmSetCoordinateField(dm, DMSwarmPICField_coor)); 17063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1707f0cdbbbaSDave May } 1708f0cdbbbaSDave May 170974d0cae8SMatthew G. Knepley /*@ 171031403186SMatthew G. Knepley DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell 171131403186SMatthew G. Knepley 171220f4b53cSBarry Smith Collective 171331403186SMatthew G. Knepley 171460225df5SJacob Faibussowitsch Input Parameters: 171520f4b53cSBarry Smith + dm - the `DMSWARM` 171620f4b53cSBarry Smith - Npc - The number of particles per cell in the cell `DM` 171731403186SMatthew G. Knepley 171831403186SMatthew G. Knepley Level: intermediate 171931403186SMatthew G. Knepley 172020f4b53cSBarry Smith Notes: 172120f4b53cSBarry Smith The user must use `DMSwarmSetCellDM()` to set the cell `DM` first. The particles are placed randomly inside each cell. If only 172220f4b53cSBarry Smith one particle is in each cell, it is placed at the centroid. 172320f4b53cSBarry Smith 172420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()` 172531403186SMatthew G. Knepley @*/ 1726d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc) 1727d71ae5a4SJacob Faibussowitsch { 172831403186SMatthew G. Knepley DM cdm; 172931403186SMatthew G. Knepley PetscRandom rnd; 173031403186SMatthew G. Knepley DMPolytopeType ct; 173131403186SMatthew G. Knepley PetscBool simplex; 173231403186SMatthew G. Knepley PetscReal *centroid, *coords, *xi0, *v0, *J, *invJ, detJ; 173331403186SMatthew G. Knepley PetscInt dim, d, cStart, cEnd, c, p; 1734d52c2f21SMatthew G. Knepley const char *coordname; 173531403186SMatthew G. Knepley 173631403186SMatthew G. Knepley PetscFunctionBeginUser; 17379566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd)); 17389566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0)); 17399566063dSJacob Faibussowitsch PetscCall(PetscRandomSetType(rnd, PETSCRAND48)); 174031403186SMatthew G. Knepley 1741d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetCoordinateField(dm, &coordname)); 17429566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &cdm)); 17439566063dSJacob Faibussowitsch PetscCall(DMGetDimension(cdm, &dim)); 17449566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd)); 17459566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(cdm, cStart, &ct)); 174631403186SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 174731403186SMatthew G. Knepley 17489566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim, ¢roid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ)); 174931403186SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 1750d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(dm, coordname, NULL, NULL, (void **)&coords)); 175131403186SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 175231403186SMatthew G. Knepley if (Npc == 1) { 17539566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL)); 175431403186SMatthew G. Knepley for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d]; 175531403186SMatthew G. Knepley } else { 17569566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */ 175731403186SMatthew G. Knepley for (p = 0; p < Npc; ++p) { 175831403186SMatthew G. Knepley const PetscInt n = c * Npc + p; 175931403186SMatthew G. Knepley PetscReal sum = 0.0, refcoords[3]; 176031403186SMatthew G. Knepley 176131403186SMatthew G. Knepley for (d = 0; d < dim; ++d) { 17629566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d])); 176331403186SMatthew G. Knepley sum += refcoords[d]; 176431403186SMatthew G. Knepley } 17659371c9d4SSatish Balay if (simplex && sum > 0.0) 17669371c9d4SSatish Balay for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum; 176731403186SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]); 176831403186SMatthew G. Knepley } 176931403186SMatthew G. Knepley } 177031403186SMatthew G. Knepley } 1771d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, coordname, NULL, NULL, (void **)&coords)); 17729566063dSJacob Faibussowitsch PetscCall(PetscFree5(centroid, xi0, v0, J, invJ)); 17739566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rnd)); 17743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 177531403186SMatthew G. Knepley } 177631403186SMatthew G. Knepley 177731403186SMatthew G. Knepley /*@ 177820f4b53cSBarry Smith DMSwarmSetType - Set particular flavor of `DMSWARM` 1779d3a51819SDave May 178020f4b53cSBarry Smith Collective 1781d3a51819SDave May 178260225df5SJacob Faibussowitsch Input Parameters: 178320f4b53cSBarry Smith + dm - the `DMSWARM` 178420f4b53cSBarry Smith - stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`) 1785d3a51819SDave May 1786d3a51819SDave May Level: advanced 1787d3a51819SDave May 178820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC` 1789d3a51819SDave May @*/ 1790d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetType(DM dm, DMSwarmType stype) 1791d71ae5a4SJacob Faibussowitsch { 1792f0cdbbbaSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1793f0cdbbbaSDave May 1794521f74f9SMatthew G. Knepley PetscFunctionBegin; 1795f0cdbbbaSDave May swarm->swarm_type = stype; 179648a46eb9SPierre Jolivet if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(dm)); 17973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1798f0cdbbbaSDave May } 1799f0cdbbbaSDave May 180066976f2fSJacob Faibussowitsch static PetscErrorCode DMSetup_Swarm(DM dm) 1801d71ae5a4SJacob Faibussowitsch { 18023454631fSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 18033454631fSDave May PetscMPIInt rank; 18043454631fSDave May PetscInt p, npoints, *rankval; 18053454631fSDave May 1806521f74f9SMatthew G. Knepley PetscFunctionBegin; 18073ba16761SJacob Faibussowitsch if (swarm->issetup) PetscFunctionReturn(PETSC_SUCCESS); 18083454631fSDave May swarm->issetup = PETSC_TRUE; 18093454631fSDave May 1810f0cdbbbaSDave May if (swarm->swarm_type == DMSWARM_PIC) { 1811f0cdbbbaSDave May /* check dmcell exists */ 1812d52c2f21SMatthew G. Knepley PetscCheck(swarm->cellinfo && swarm->cellinfo[0].dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires you call DMSwarmSetCellDM() or DMSwarmPushCellDM()"); 1813f0cdbbbaSDave May 1814d52c2f21SMatthew G. Knepley if (swarm->cellinfo[0].dm->ops->locatepointssubdomain) { 1815f0cdbbbaSDave May /* check methods exists for exact ownership identificiation */ 18169566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n")); 1817f0cdbbbaSDave May swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT; 1818f0cdbbbaSDave May } else { 1819f0cdbbbaSDave May /* check methods exist for point location AND rank neighbor identification */ 1820d52c2f21SMatthew G. Knepley if (swarm->cellinfo[0].dm->ops->locatepoints) { 18219566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n")); 1822f0cdbbbaSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined"); 1823f0cdbbbaSDave May 1824d52c2f21SMatthew G. Knepley if (swarm->cellinfo[0].dm->ops->getneighbors) { 18259566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n")); 1826f0cdbbbaSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined"); 1827f0cdbbbaSDave May 1828f0cdbbbaSDave May swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER; 1829f0cdbbbaSDave May } 1830f0cdbbbaSDave May } 1831f0cdbbbaSDave May 18329566063dSJacob Faibussowitsch PetscCall(DMSwarmFinalizeFieldRegister(dm)); 1833f0cdbbbaSDave May 18343454631fSDave May /* check some fields were registered */ 183508401ef6SPierre Jolivet PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()"); 18363454631fSDave May 18373454631fSDave May /* check local sizes were set */ 183808401ef6SPierre Jolivet PetscCheck(swarm->db->L != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Local sizes must be set via DMSwarmSetLocalSizes()"); 18393454631fSDave May 18403454631fSDave May /* initialize values in pid and rank placeholders */ 18413454631fSDave May /* TODO: [pid - use MPI_Scan] */ 18429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 18439566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL)); 18449566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval)); 1845835f2295SStefano Zampini for (p = 0; p < npoints; p++) rankval[p] = rank; 18469566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval)); 18473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18483454631fSDave May } 18493454631fSDave May 1850dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx); 1851dc5f5ce9SDave May 185266976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroy_Swarm(DM dm) 1853d71ae5a4SJacob Faibussowitsch { 185457795646SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1855d52c2f21SMatthew G. Knepley CellDMInfo info = swarm->cellinfo; 185657795646SDave May 185757795646SDave May PetscFunctionBegin; 18583ba16761SJacob Faibussowitsch if (--swarm->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 18599566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketDestroy(&swarm->db)); 1860d52c2f21SMatthew G. Knepley for (PetscInt f = 0; f < swarm->vec_field_num; ++f) PetscCall(PetscFree(swarm->vec_field_names[f])); 1861d52c2f21SMatthew G. Knepley PetscCall(PetscFree(swarm->vec_field_names)); 1862d52c2f21SMatthew G. Knepley PetscCall(PetscFree(swarm->coord_name)); 186348a46eb9SPierre Jolivet if (swarm->sort_context) PetscCall(DMSwarmSortDestroy(&swarm->sort_context)); 1864d52c2f21SMatthew G. Knepley while (info) { 1865d52c2f21SMatthew G. Knepley CellDMInfo tmp = info; 1866d52c2f21SMatthew G. Knepley 1867d52c2f21SMatthew G. Knepley info = info->next; 1868d52c2f21SMatthew G. Knepley PetscCall(CellDMInfoDestroy(&tmp)); 1869d52c2f21SMatthew G. Knepley } 18709566063dSJacob Faibussowitsch PetscCall(PetscFree(swarm)); 18713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 187257795646SDave May } 187357795646SDave May 187466976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer) 1875d71ae5a4SJacob Faibussowitsch { 1876a9ee3421SMatthew G. Knepley DM cdm; 1877a9ee3421SMatthew G. Knepley PetscDraw draw; 187831403186SMatthew G. Knepley PetscReal *coords, oldPause, radius = 0.01; 1879a9ee3421SMatthew G. Knepley PetscInt Np, p, bs; 1880d52c2f21SMatthew G. Knepley const char *coordname; 1881a9ee3421SMatthew G. Knepley 1882a9ee3421SMatthew G. Knepley PetscFunctionBegin; 18839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL)); 18849566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 18859566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &cdm)); 18869566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &oldPause)); 18879566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, 0.0)); 18889566063dSJacob Faibussowitsch PetscCall(DMView(cdm, viewer)); 18899566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, oldPause)); 1890a9ee3421SMatthew G. Knepley 1891d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetCoordinateField(dm, &coordname)); 18929566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &Np)); 1893d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(dm, coordname, &bs, NULL, (void **)&coords)); 1894a9ee3421SMatthew G. Knepley for (p = 0; p < Np; ++p) { 1895a9ee3421SMatthew G. Knepley const PetscInt i = p * bs; 1896a9ee3421SMatthew G. Knepley 18979566063dSJacob Faibussowitsch PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE)); 1898a9ee3421SMatthew G. Knepley } 1899d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, coordname, &bs, NULL, (void **)&coords)); 19009566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 19019566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 19029566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 19033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1904a9ee3421SMatthew G. Knepley } 1905a9ee3421SMatthew G. Knepley 1906d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer) 1907d71ae5a4SJacob Faibussowitsch { 19086a5217c0SMatthew G. Knepley PetscViewerFormat format; 19096a5217c0SMatthew G. Knepley PetscInt *sizes; 19106a5217c0SMatthew G. Knepley PetscInt dim, Np, maxSize = 17; 19116a5217c0SMatthew G. Knepley MPI_Comm comm; 19126a5217c0SMatthew G. Knepley PetscMPIInt rank, size, p; 19136a5217c0SMatthew G. Knepley const char *name; 19146a5217c0SMatthew G. Knepley 19156a5217c0SMatthew G. Knepley PetscFunctionBegin; 19166a5217c0SMatthew G. Knepley PetscCall(PetscViewerGetFormat(viewer, &format)); 19176a5217c0SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 19186a5217c0SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(dm, &Np)); 19196a5217c0SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19206a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 19216a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(comm, &size)); 19226a5217c0SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 192363a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 192463a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 19256a5217c0SMatthew G. Knepley if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes)); 19266a5217c0SMatthew G. Knepley else PetscCall(PetscCalloc1(3, &sizes)); 19276a5217c0SMatthew G. Knepley if (size < maxSize) { 19286a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 19296a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Number of particles per rank:")); 19306a5217c0SMatthew G. Knepley for (p = 0; p < size; ++p) { 19316a5217c0SMatthew G. Knepley if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p])); 19326a5217c0SMatthew G. Knepley } 19336a5217c0SMatthew G. Knepley } else { 19346a5217c0SMatthew G. Knepley PetscInt locMinMax[2] = {Np, Np}; 19356a5217c0SMatthew G. Knepley 19366a5217c0SMatthew G. Knepley PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 19376a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 19386a5217c0SMatthew G. Knepley } 19396a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 19406a5217c0SMatthew G. Knepley PetscCall(PetscFree(sizes)); 19416a5217c0SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO) { 19426a5217c0SMatthew G. Knepley PetscInt *cell; 19436a5217c0SMatthew G. Knepley 19446a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Cells containing each particle:\n")); 19456a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 19466a5217c0SMatthew G. Knepley PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell)); 194763a3b9bcSJacob Faibussowitsch for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " p%d: %" PetscInt_FMT "\n", p, cell[p])); 19486a5217c0SMatthew G. Knepley PetscCall(PetscViewerFlush(viewer)); 19496a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 19506a5217c0SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell)); 19516a5217c0SMatthew G. Knepley } 19523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19536a5217c0SMatthew G. Knepley } 19546a5217c0SMatthew G. Knepley 195566976f2fSJacob Faibussowitsch static PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer) 1956d71ae5a4SJacob Faibussowitsch { 19575f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 19584fc69c0aSMatthew G. Knepley PetscBool iascii, ibinary, isvtk, isdraw, ispython; 19595627991aSBarry Smith #if defined(PETSC_HAVE_HDF5) 19605627991aSBarry Smith PetscBool ishdf5; 19615627991aSBarry Smith #endif 19625f50eb2eSDave May 19635f50eb2eSDave May PetscFunctionBegin; 19645f50eb2eSDave May PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19655f50eb2eSDave May PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 19669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 19679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary)); 19689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 19695627991aSBarry Smith #if defined(PETSC_HAVE_HDF5) 19709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 19715627991aSBarry Smith #endif 19729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 19734fc69c0aSMatthew G. Knepley PetscCall(PetscObjectHasFunction((PetscObject)viewer, "PetscViewerPythonViewObject_C", &ispython)); 19745f50eb2eSDave May if (iascii) { 19756a5217c0SMatthew G. Knepley PetscViewerFormat format; 19766a5217c0SMatthew G. Knepley 19776a5217c0SMatthew G. Knepley PetscCall(PetscViewerGetFormat(viewer, &format)); 19786a5217c0SMatthew G. Knepley switch (format) { 1979d71ae5a4SJacob Faibussowitsch case PETSC_VIEWER_ASCII_INFO_DETAIL: 1980d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT)); 1981d71ae5a4SJacob Faibussowitsch break; 1982d71ae5a4SJacob Faibussowitsch default: 1983d71ae5a4SJacob Faibussowitsch PetscCall(DMView_Swarm_Ascii(dm, viewer)); 19846a5217c0SMatthew G. Knepley } 1985f7d195e4SLawrence Mitchell } else { 19865f50eb2eSDave May #if defined(PETSC_HAVE_HDF5) 198748a46eb9SPierre Jolivet if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer)); 19885f50eb2eSDave May #endif 198948a46eb9SPierre Jolivet if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer)); 19904fc69c0aSMatthew G. Knepley if (ispython) PetscCall(PetscViewerPythonViewObject(viewer, (PetscObject)dm)); 1991f7d195e4SLawrence Mitchell } 19923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19935f50eb2eSDave May } 19945f50eb2eSDave May 1995cc4c1da9SBarry Smith /*@ 199620f4b53cSBarry Smith DMSwarmGetCellSwarm - Extracts a single cell from the `DMSWARM` object, returns it as a single cell `DMSWARM`. 199720f4b53cSBarry 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. 1998d0c080abSJoseph Pusztay 1999d0c080abSJoseph Pusztay Noncollective 2000d0c080abSJoseph Pusztay 200160225df5SJacob Faibussowitsch Input Parameters: 200220f4b53cSBarry Smith + sw - the `DMSWARM` 20035627991aSBarry Smith . cellID - the integer id of the cell to be extracted and filtered 200420f4b53cSBarry Smith - cellswarm - The `DMSWARM` to receive the cell 2005d0c080abSJoseph Pusztay 2006d0c080abSJoseph Pusztay Level: beginner 2007d0c080abSJoseph Pusztay 20085627991aSBarry Smith Notes: 200920f4b53cSBarry Smith This presently only supports `DMSWARM_PIC` type 20105627991aSBarry Smith 201120f4b53cSBarry Smith Should be restored with `DMSwarmRestoreCellSwarm()` 2012d0c080abSJoseph Pusztay 201320f4b53cSBarry Smith Changes to this cell of the swarm will be lost if they are made prior to restoring this cell. 201420f4b53cSBarry Smith 201520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreCellSwarm()` 2016d0c080abSJoseph Pusztay @*/ 2017cc4c1da9SBarry Smith PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm) 2018d71ae5a4SJacob Faibussowitsch { 2019d0c080abSJoseph Pusztay DM_Swarm *original = (DM_Swarm *)sw->data; 2020d0c080abSJoseph Pusztay DMLabel label; 2021d0c080abSJoseph Pusztay DM dmc, subdmc; 2022d0c080abSJoseph Pusztay PetscInt *pids, particles, dim; 2023d0c080abSJoseph Pusztay 2024d0c080abSJoseph Pusztay PetscFunctionBegin; 2025d0c080abSJoseph Pusztay /* Configure new swarm */ 20269566063dSJacob Faibussowitsch PetscCall(DMSetType(cellswarm, DMSWARM)); 20279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 20289566063dSJacob Faibussowitsch PetscCall(DMSetDimension(cellswarm, dim)); 20299566063dSJacob Faibussowitsch PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC)); 2030d0c080abSJoseph Pusztay /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */ 20319566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db)); 20329566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 20339566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles)); 20349566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids)); 20359566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db)); 20369566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 2037fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids)); 20389566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(sw, &dmc)); 20399566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label)); 20409566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmc, label)); 20419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cellID, 1)); 204230cbcd5dSksagiyam PetscCall(DMPlexFilter(dmc, label, 1, PETSC_FALSE, PETSC_FALSE, NULL, &subdmc)); 20439566063dSJacob Faibussowitsch PetscCall(DMSwarmSetCellDM(cellswarm, subdmc)); 20449566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&label)); 20453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2046d0c080abSJoseph Pusztay } 2047d0c080abSJoseph Pusztay 2048cc4c1da9SBarry Smith /*@ 204920f4b53cSBarry Smith DMSwarmRestoreCellSwarm - Restores a `DMSWARM` object obtained with `DMSwarmGetCellSwarm()`. All fields are copied back into the parent swarm. 2050d0c080abSJoseph Pusztay 2051d0c080abSJoseph Pusztay Noncollective 2052d0c080abSJoseph Pusztay 205360225df5SJacob Faibussowitsch Input Parameters: 205420f4b53cSBarry Smith + sw - the parent `DMSWARM` 2055d0c080abSJoseph Pusztay . cellID - the integer id of the cell to be copied back into the parent swarm 2056d0c080abSJoseph Pusztay - cellswarm - the cell swarm object 2057d0c080abSJoseph Pusztay 2058d0c080abSJoseph Pusztay Level: beginner 2059d0c080abSJoseph Pusztay 20605627991aSBarry Smith Note: 206120f4b53cSBarry Smith This only supports `DMSWARM_PIC` types of `DMSWARM`s 2062d0c080abSJoseph Pusztay 206320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetCellSwarm()` 2064d0c080abSJoseph Pusztay @*/ 2065cc4c1da9SBarry Smith PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm) 2066d71ae5a4SJacob Faibussowitsch { 2067d0c080abSJoseph Pusztay DM dmc; 2068d0c080abSJoseph Pusztay PetscInt *pids, particles, p; 2069d0c080abSJoseph Pusztay 2070d0c080abSJoseph Pusztay PetscFunctionBegin; 20719566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 20729566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids)); 20739566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 2074d0c080abSJoseph Pusztay /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */ 207548a46eb9SPierre Jolivet for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p])); 2076d0c080abSJoseph Pusztay /* Free memory, destroy cell dm */ 20779566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(cellswarm, &dmc)); 20789566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 2079fe11354eSMatthew G. Knepley PetscCall(DMSwarmSortRestorePointsPerCell(sw, cellID, &particles, &pids)); 20803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2081d0c080abSJoseph Pusztay } 2082d0c080abSJoseph Pusztay 2083d52c2f21SMatthew G. Knepley /*@ 2084d52c2f21SMatthew G. Knepley DMSwarmComputeMoments - Compute the first three particle moments for a given field 2085d52c2f21SMatthew G. Knepley 2086d52c2f21SMatthew G. Knepley Noncollective 2087d52c2f21SMatthew G. Knepley 2088d52c2f21SMatthew G. Knepley Input Parameters: 2089d52c2f21SMatthew G. Knepley + sw - the `DMSWARM` 2090d52c2f21SMatthew G. Knepley . coordinate - the coordinate field name 2091d52c2f21SMatthew G. Knepley - weight - the weight field name 2092d52c2f21SMatthew G. Knepley 2093d52c2f21SMatthew G. Knepley Output Parameter: 2094d52c2f21SMatthew G. Knepley . moments - the field moments 2095d52c2f21SMatthew G. Knepley 2096d52c2f21SMatthew G. Knepley Level: intermediate 2097d52c2f21SMatthew G. Knepley 2098d52c2f21SMatthew G. Knepley Notes: 2099d52c2f21SMatthew G. Knepley The `moments` array should be of length bs + 2, where bs is the block size of the coordinate field. 2100d52c2f21SMatthew G. Knepley 2101d52c2f21SMatthew G. Knepley The weight field must be a scalar, having blocksize 1. 2102d52c2f21SMatthew G. Knepley 2103d52c2f21SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMPlexComputeMoments()` 2104d52c2f21SMatthew G. Knepley @*/ 2105d52c2f21SMatthew G. Knepley PetscErrorCode DMSwarmComputeMoments(DM sw, const char coordinate[], const char weight[], PetscReal moments[]) 2106d52c2f21SMatthew G. Knepley { 2107d52c2f21SMatthew G. Knepley const PetscReal *coords; 2108d52c2f21SMatthew G. Knepley const PetscReal *w; 2109d52c2f21SMatthew G. Knepley PetscReal *mom; 2110d52c2f21SMatthew G. Knepley PetscDataType dtc, dtw; 2111d52c2f21SMatthew G. Knepley PetscInt bsc, bsw, Np; 2112d52c2f21SMatthew G. Knepley MPI_Comm comm; 2113d52c2f21SMatthew G. Knepley 2114d52c2f21SMatthew G. Knepley PetscFunctionBegin; 2115d52c2f21SMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 2116d52c2f21SMatthew G. Knepley PetscAssertPointer(coordinate, 2); 2117d52c2f21SMatthew G. Knepley PetscAssertPointer(weight, 3); 2118d52c2f21SMatthew G. Knepley PetscAssertPointer(moments, 4); 2119d52c2f21SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)sw, &comm)); 2120d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, coordinate, &bsc, &dtc, (void **)&coords)); 2121d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetField(sw, weight, &bsw, &dtw, (void **)&w)); 2122d52c2f21SMatthew G. Knepley PetscCheck(dtc == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Coordinate field %s must be real, not %s", coordinate, PetscDataTypes[dtc]); 2123d52c2f21SMatthew G. Knepley PetscCheck(dtw == PETSC_REAL, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be real, not %s", weight, PetscDataTypes[dtw]); 2124d52c2f21SMatthew G. Knepley PetscCheck(bsw == 1, comm, PETSC_ERR_ARG_WRONG, "Weight field %s must be a scalar, not blocksize %" PetscInt_FMT, weight, bsw); 2125d52c2f21SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 2126d52c2f21SMatthew G. Knepley PetscCall(DMGetWorkArray(sw, bsc + 2, MPIU_REAL, &mom)); 2127d52c2f21SMatthew G. Knepley PetscCall(PetscArrayzero(mom, bsc + 2)); 2128d52c2f21SMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 2129d52c2f21SMatthew G. Knepley const PetscReal *c = &coords[p * bsc]; 2130d52c2f21SMatthew G. Knepley const PetscReal wp = w[p]; 2131d52c2f21SMatthew G. Knepley 2132d52c2f21SMatthew G. Knepley mom[0] += wp; 2133d52c2f21SMatthew G. Knepley for (PetscInt d = 0; d < bsc; ++d) { 2134d52c2f21SMatthew G. Knepley mom[d + 1] += wp * c[d]; 2135d52c2f21SMatthew G. Knepley mom[d + bsc + 1] += wp * PetscSqr(c[d]); 2136d52c2f21SMatthew G. Knepley } 2137d52c2f21SMatthew G. Knepley } 2138d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&coords)); 2139d52c2f21SMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&w)); 2140d52c2f21SMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(mom, moments, bsc + 2, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)sw))); 2141d52c2f21SMatthew G. Knepley PetscCall(DMRestoreWorkArray(sw, bsc + 2, MPIU_REAL, &mom)); 2142d0c080abSJoseph Pusztay PetscFunctionReturn(PETSC_SUCCESS); 2143d0c080abSJoseph Pusztay } 2144d0c080abSJoseph Pusztay 2145d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *); 2146d0c080abSJoseph Pusztay 2147d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Swarm(DM sw) 2148d71ae5a4SJacob Faibussowitsch { 2149d0c080abSJoseph Pusztay PetscFunctionBegin; 2150d0c080abSJoseph Pusztay sw->ops->view = DMView_Swarm; 2151d0c080abSJoseph Pusztay sw->ops->load = NULL; 2152d0c080abSJoseph Pusztay sw->ops->setfromoptions = NULL; 2153d0c080abSJoseph Pusztay sw->ops->clone = DMClone_Swarm; 2154d0c080abSJoseph Pusztay sw->ops->setup = DMSetup_Swarm; 2155d0c080abSJoseph Pusztay sw->ops->createlocalsection = NULL; 2156adc21957SMatthew G. Knepley sw->ops->createsectionpermutation = NULL; 2157d0c080abSJoseph Pusztay sw->ops->createdefaultconstraints = NULL; 2158d0c080abSJoseph Pusztay sw->ops->createglobalvector = DMCreateGlobalVector_Swarm; 2159d0c080abSJoseph Pusztay sw->ops->createlocalvector = DMCreateLocalVector_Swarm; 2160d0c080abSJoseph Pusztay sw->ops->getlocaltoglobalmapping = NULL; 2161d0c080abSJoseph Pusztay sw->ops->createfieldis = NULL; 2162d0c080abSJoseph Pusztay sw->ops->createcoordinatedm = NULL; 2163d0c080abSJoseph Pusztay sw->ops->getcoloring = NULL; 2164d0c080abSJoseph Pusztay sw->ops->creatematrix = DMCreateMatrix_Swarm; 2165d0c080abSJoseph Pusztay sw->ops->createinterpolation = NULL; 2166d0c080abSJoseph Pusztay sw->ops->createinjection = NULL; 2167d0c080abSJoseph Pusztay sw->ops->createmassmatrix = DMCreateMassMatrix_Swarm; 2168d0c080abSJoseph Pusztay sw->ops->refine = NULL; 2169d0c080abSJoseph Pusztay sw->ops->coarsen = NULL; 2170d0c080abSJoseph Pusztay sw->ops->refinehierarchy = NULL; 2171d0c080abSJoseph Pusztay sw->ops->coarsenhierarchy = NULL; 2172d0c080abSJoseph Pusztay sw->ops->globaltolocalbegin = NULL; 2173d0c080abSJoseph Pusztay sw->ops->globaltolocalend = NULL; 2174d0c080abSJoseph Pusztay sw->ops->localtoglobalbegin = NULL; 2175d0c080abSJoseph Pusztay sw->ops->localtoglobalend = NULL; 2176d0c080abSJoseph Pusztay sw->ops->destroy = DMDestroy_Swarm; 2177d0c080abSJoseph Pusztay sw->ops->createsubdm = NULL; 2178d0c080abSJoseph Pusztay sw->ops->getdimpoints = NULL; 2179d0c080abSJoseph Pusztay sw->ops->locatepoints = NULL; 21803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2181d0c080abSJoseph Pusztay } 2182d0c080abSJoseph Pusztay 2183d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm) 2184d71ae5a4SJacob Faibussowitsch { 2185d0c080abSJoseph Pusztay DM_Swarm *swarm = (DM_Swarm *)dm->data; 2186d0c080abSJoseph Pusztay 2187d0c080abSJoseph Pusztay PetscFunctionBegin; 2188d0c080abSJoseph Pusztay swarm->refct++; 2189d0c080abSJoseph Pusztay (*newdm)->data = swarm; 21909566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM)); 21919566063dSJacob Faibussowitsch PetscCall(DMInitialize_Swarm(*newdm)); 21922e56dffeSJoe Pusztay (*newdm)->dim = dm->dim; 21933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2194d0c080abSJoseph Pusztay } 2195d0c080abSJoseph Pusztay 2196d3a51819SDave May /*MC 219720f4b53cSBarry Smith DMSWARM = "swarm" - A `DM` object used to represent arrays of data (fields) of arbitrary data type. 219862741f57SDave May This implementation was designed for particle methods in which the underlying 2199d3a51819SDave May data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type. 2200d3a51819SDave May 220120f4b53cSBarry Smith Level: intermediate 220220f4b53cSBarry Smith 220320f4b53cSBarry Smith Notes: 220420f4b53cSBarry Smith User data can be represented by `DMSWARM` through a registering "fields". 220562741f57SDave May To register a field, the user must provide; 220662741f57SDave May (a) a unique name; 220762741f57SDave May (b) the data type (or size in bytes); 220862741f57SDave May (c) the block size of the data. 2209d3a51819SDave May 2210d3a51819SDave May For example, suppose the application requires a unique id, energy, momentum and density to be stored 2211c215a47eSMatthew Knepley on a set of particles. Then the following code could be used 221220f4b53cSBarry Smith .vb 221320f4b53cSBarry Smith DMSwarmInitializeFieldRegister(dm) 221420f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG); 221520f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL); 221620f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL); 221720f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT); 221820f4b53cSBarry Smith DMSwarmFinalizeFieldRegister(dm) 221920f4b53cSBarry Smith .ve 2220d3a51819SDave May 222120f4b53cSBarry Smith The fields represented by `DMSWARM` are dynamic and can be re-sized at any time. 222220f4b53cSBarry Smith The only restriction imposed by `DMSWARM` is that all fields contain the same number of points. 2223d3a51819SDave May 2224d3a51819SDave May To support particle methods, "migration" techniques are provided. These methods migrate data 22255627991aSBarry Smith between ranks. 2226d3a51819SDave May 222720f4b53cSBarry Smith `DMSWARM` supports the methods `DMCreateGlobalVector()` and `DMCreateLocalVector()`. 222820f4b53cSBarry Smith As a `DMSWARM` may internally define and store values of different data types, 222920f4b53cSBarry Smith before calling `DMCreateGlobalVector()` or `DMCreateLocalVector()`, the user must inform `DMSWARM` which 223020f4b53cSBarry Smith fields should be used to define a `Vec` object via 223120f4b53cSBarry Smith `DMSwarmVectorDefineField()` 2232c215a47eSMatthew Knepley The specified field can be changed at any time - thereby permitting vectors 2233c215a47eSMatthew Knepley compatible with different fields to be created. 2234d3a51819SDave May 223520f4b53cSBarry Smith A dual representation of fields in the `DMSWARM` and a Vec object is permitted via 223620f4b53cSBarry Smith `DMSwarmCreateGlobalVectorFromField()` 223720f4b53cSBarry Smith Here the data defining the field in the `DMSWARM` is shared with a Vec. 2238d3a51819SDave May This is inherently unsafe if you alter the size of the field at any time between 223920f4b53cSBarry Smith calls to `DMSwarmCreateGlobalVectorFromField()` and `DMSwarmDestroyGlobalVectorFromField()`. 224020f4b53cSBarry Smith If the local size of the `DMSWARM` does not match the local size of the global vector 224120f4b53cSBarry Smith when `DMSwarmDestroyGlobalVectorFromField()` is called, an error is thrown. 2242d3a51819SDave May 224362741f57SDave May Additional high-level support is provided for Particle-In-Cell methods. 224420f4b53cSBarry Smith Please refer to `DMSwarmSetType()`. 224562741f57SDave May 224620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMType`, `DMCreate()`, `DMSetType()` 2247d3a51819SDave May M*/ 2248cc4c1da9SBarry Smith 2249d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm) 2250d71ae5a4SJacob Faibussowitsch { 225157795646SDave May DM_Swarm *swarm; 225257795646SDave May 225357795646SDave May PetscFunctionBegin; 225457795646SDave May PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22554dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&swarm)); 2256f0cdbbbaSDave May dm->data = swarm; 22579566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCreate(&swarm->db)); 22589566063dSJacob Faibussowitsch PetscCall(DMSwarmInitializeFieldRegister(dm)); 2259d52c2f21SMatthew G. Knepley dm->dim = 0; 2260d0c080abSJoseph Pusztay swarm->refct = 1; 22613454631fSDave May swarm->issetup = PETSC_FALSE; 2262480eef7bSDave May swarm->swarm_type = DMSWARM_BASIC; 2263480eef7bSDave May swarm->migrate_type = DMSWARM_MIGRATE_BASIC; 2264480eef7bSDave May swarm->collect_type = DMSWARM_COLLECT_BASIC; 226540c453e9SDave May swarm->migrate_error_on_missing_point = PETSC_FALSE; 2266d52c2f21SMatthew G. Knepley swarm->cellinfo = NULL; 2267f0cdbbbaSDave May swarm->collect_view_active = PETSC_FALSE; 2268f0cdbbbaSDave May swarm->collect_view_reset_nlocal = -1; 22699566063dSJacob Faibussowitsch PetscCall(DMInitialize_Swarm(dm)); 22702e956fe4SStefano Zampini if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId)); 22713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 227257795646SDave May } 2273