157795646SDave May #define PETSCDM_DLL 257795646SDave May #include <petsc/private/dmswarmimpl.h> /*I "petscdmswarm.h" I*/ 3e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h> 40643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> 55917a6f0SStefano Zampini #include <petscviewer.h> 65917a6f0SStefano Zampini #include <petscdraw.h> 783c47955SMatthew G. Knepley #include <petscdmplex.h> 84cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h> 9279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h" 10d0c080abSJoseph Pusztay #include <petscdmlabel.h> 11d0c080abSJoseph Pusztay #include <petscsection.h> 1257795646SDave May 13f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort; 14ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd; 15ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack; 16ed923d71SDave May 17ea78f98cSLisandro Dalcin const char *DMSwarmTypeNames[] = {"basic", "pic", NULL}; 18ea78f98cSLisandro Dalcin const char *DMSwarmMigrateTypeNames[] = {"basic", "dmcellnscatter", "dmcellexact", "user", NULL}; 19ea78f98cSLisandro Dalcin const char *DMSwarmCollectTypeNames[] = {"basic", "boundingbox", "general", "user", NULL}; 20ea78f98cSLisandro Dalcin const char *DMSwarmPICLayoutTypeNames[] = {"regular", "gauss", "subdivision", NULL}; 21f0cdbbbaSDave May 22f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid"; 23f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank"; 24f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor"; 25e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid"; 26f0cdbbbaSDave May 272e956fe4SStefano Zampini PetscInt SwarmDataFieldId = -1; 282e956fe4SStefano Zampini 2974d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5) 3074d0cae8SMatthew G. Knepley #include <petscviewerhdf5.h> 3174d0cae8SMatthew G. Knepley 3266976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer) 33d71ae5a4SJacob Faibussowitsch { 3474d0cae8SMatthew G. Knepley DM dm; 3574d0cae8SMatthew G. Knepley PetscReal seqval; 3674d0cae8SMatthew G. Knepley PetscInt seqnum, bs; 37eb0c6899SMatthew G. Knepley PetscBool isseq, ists; 3874d0cae8SMatthew G. Knepley 3974d0cae8SMatthew G. Knepley PetscFunctionBegin; 409566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 419566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &bs)); 429566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PushGroup(viewer, "/particle_fields")); 439566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq)); 449566063dSJacob Faibussowitsch PetscCall(DMGetOutputSequenceNumber(dm, &seqnum, &seqval)); 45eb0c6899SMatthew G. Knepley PetscCall(PetscViewerHDF5IsTimestepping(viewer, &ists)); 46eb0c6899SMatthew G. Knepley if (ists) PetscCall(PetscViewerHDF5SetTimestep(viewer, seqnum)); 479566063dSJacob Faibussowitsch /* PetscCall(DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer)); */ 489566063dSJacob Faibussowitsch PetscCall(VecViewNative(v, viewer)); 499566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)v, "Nc", PETSC_INT, (void *)&bs)); 509566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PopGroup(viewer)); 513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5274d0cae8SMatthew G. Knepley } 5374d0cae8SMatthew G. Knepley 5466976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer) 55d71ae5a4SJacob Faibussowitsch { 5674d0cae8SMatthew G. Knepley Vec coordinates; 5774d0cae8SMatthew G. Knepley PetscInt Np; 5874d0cae8SMatthew G. Knepley PetscBool isseq; 5974d0cae8SMatthew G. Knepley 6074d0cae8SMatthew G. Knepley PetscFunctionBegin; 619566063dSJacob Faibussowitsch PetscCall(DMSwarmGetSize(dm, &Np)); 629566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates)); 639566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 649566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PushGroup(viewer, "/particles")); 659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)coordinates, VECSEQ, &isseq)); 669566063dSJacob Faibussowitsch PetscCall(VecViewNative(coordinates, viewer)); 679566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject)coordinates, "Np", PETSC_INT, (void *)&Np)); 689566063dSJacob Faibussowitsch PetscCall(PetscViewerHDF5PopGroup(viewer)); 699566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates)); 703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7174d0cae8SMatthew G. Knepley } 7274d0cae8SMatthew G. Knepley #endif 7374d0cae8SMatthew G. Knepley 7466976f2fSJacob Faibussowitsch static PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer) 75d71ae5a4SJacob Faibussowitsch { 7674d0cae8SMatthew G. Knepley DM dm; 77f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5) 7874d0cae8SMatthew G. Knepley PetscBool ishdf5; 79f9558f5cSBarry Smith #endif 8074d0cae8SMatthew G. Knepley 8174d0cae8SMatthew G. Knepley PetscFunctionBegin; 829566063dSJacob Faibussowitsch PetscCall(VecGetDM(v, &dm)); 8328b400f6SJacob Faibussowitsch PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5) 859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 8674d0cae8SMatthew G. Knepley if (ishdf5) { 879566063dSJacob Faibussowitsch PetscCall(VecView_Swarm_HDF5_Internal(v, viewer)); 883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8974d0cae8SMatthew G. Knepley } 90f9558f5cSBarry Smith #endif 919566063dSJacob Faibussowitsch PetscCall(VecViewNative(v, viewer)); 923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9374d0cae8SMatthew G. Knepley } 9474d0cae8SMatthew G. Knepley 95cc4c1da9SBarry Smith /*@ 960bf7c1c5SMatthew G. Knepley DMSwarmVectorGetField - Gets the field from which to define a `Vec` object 970bf7c1c5SMatthew G. Knepley when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 980bf7c1c5SMatthew G. Knepley 990bf7c1c5SMatthew G. Knepley Not collective 1000bf7c1c5SMatthew G. Knepley 1010bf7c1c5SMatthew G. Knepley Input Parameter: 1020bf7c1c5SMatthew G. Knepley . dm - a `DMSWARM` 1030bf7c1c5SMatthew G. Knepley 1040bf7c1c5SMatthew G. Knepley Output Parameter: 1050bf7c1c5SMatthew G. Knepley . fieldname - the textual name given to a registered field, or the empty string if it has not been set 1060bf7c1c5SMatthew G. Knepley 1070bf7c1c5SMatthew G. Knepley Level: beginner 1080bf7c1c5SMatthew G. Knepley 1090bf7c1c5SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorDefineField()` `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 1100bf7c1c5SMatthew G. Knepley @*/ 1110bf7c1c5SMatthew G. Knepley PetscErrorCode DMSwarmVectorGetField(DM dm, const char *fieldname[]) 1120bf7c1c5SMatthew G. Knepley { 1130bf7c1c5SMatthew G. Knepley PetscFunctionBegin; 1140bf7c1c5SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 1150bf7c1c5SMatthew G. Knepley PetscAssertPointer(fieldname, 2); 1160bf7c1c5SMatthew G. Knepley *fieldname = ((DM_Swarm *)dm->data)->vec_field_name; 1170bf7c1c5SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 1180bf7c1c5SMatthew G. Knepley } 1190bf7c1c5SMatthew G. Knepley 120cc4c1da9SBarry Smith /*@ 12120f4b53cSBarry Smith DMSwarmVectorDefineField - Sets the field from which to define a `Vec` object 12220f4b53cSBarry Smith when `DMCreateLocalVector()`, or `DMCreateGlobalVector()` is called 12357795646SDave May 12420f4b53cSBarry Smith Collective 12557795646SDave May 12660225df5SJacob Faibussowitsch Input Parameters: 12720f4b53cSBarry Smith + dm - a `DMSWARM` 12862741f57SDave May - fieldname - the textual name given to a registered field 12957795646SDave May 130d3a51819SDave May Level: beginner 13157795646SDave May 132d3a51819SDave May Notes: 13320f4b53cSBarry Smith The field with name `fieldname` must be defined as having a data type of `PetscScalar`. 134e7af74c8SDave May 13520f4b53cSBarry Smith This function must be called prior to calling `DMCreateLocalVector()`, `DMCreateGlobalVector()`. 13620f4b53cSBarry Smith Multiple calls to `DMSwarmVectorDefineField()` are permitted. 137e7af74c8SDave May 1380bf7c1c5SMatthew G. Knepley .seealso: `DM`, `DMSWARM`, `DMSwarmVectorGetField()`, `DMSwarmRegisterPetscDatatypeField()`, `DMCreateGlobalVector()`, `DMCreateLocalVector()` 139d3a51819SDave May @*/ 140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmVectorDefineField(DM dm, const char fieldname[]) 141d71ae5a4SJacob Faibussowitsch { 142b5bcf523SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 143b5bcf523SDave May PetscInt bs, n; 144b5bcf523SDave May PetscScalar *array; 145b5bcf523SDave May PetscDataType type; 146b5bcf523SDave May 147a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 1480bf7c1c5SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 1490bf7c1c5SMatthew G. Knepley if (fieldname) PetscAssertPointer(fieldname, 2); 1509566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 1519566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL)); 1529566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array)); 153b5bcf523SDave May 154b5bcf523SDave May /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */ 15508401ef6SPierre Jolivet PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 1569566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(swarm->vec_field_name, PETSC_MAX_PATH_LEN - 1, "%s", fieldname)); 157b5bcf523SDave May swarm->vec_field_set = PETSC_TRUE; 1581b1ea282SDave May swarm->vec_field_bs = bs; 159b5bcf523SDave May swarm->vec_field_nlocal = n; 1609566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, fieldname, &bs, &type, (void **)&array)); 1613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 162b5bcf523SDave May } 163b5bcf523SDave May 164cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */ 16566976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Swarm(DM dm, Vec *vec) 166d71ae5a4SJacob Faibussowitsch { 167b5bcf523SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 168b5bcf523SDave May Vec x; 169b5bcf523SDave May char name[PETSC_MAX_PATH_LEN]; 170b5bcf523SDave May 171a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 1729566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 17328b400f6SJacob Faibussowitsch PetscCheck(swarm->vec_field_set, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField first"); 17408401ef6SPierre Jolivet PetscCheck(swarm->vec_field_nlocal == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */ 175cc651181SDave May 1769566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmField_%s", swarm->vec_field_name)); 1779566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &x)); 1789566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)x, name)); 1799566063dSJacob Faibussowitsch PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE)); 1809566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(x, swarm->vec_field_bs)); 1819566063dSJacob Faibussowitsch PetscCall(VecSetDM(x, dm)); 1829566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(x)); 1839566063dSJacob Faibussowitsch PetscCall(VecSetDM(x, dm)); 1849566063dSJacob Faibussowitsch PetscCall(VecSetOperation(x, VECOP_VIEW, (void (*)(void))VecView_Swarm)); 185b5bcf523SDave May *vec = x; 1863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 187b5bcf523SDave May } 188b5bcf523SDave May 189b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */ 19066976f2fSJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Swarm(DM dm, Vec *vec) 191d71ae5a4SJacob Faibussowitsch { 192b5bcf523SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 193b5bcf523SDave May Vec x; 194b5bcf523SDave May char name[PETSC_MAX_PATH_LEN]; 195b5bcf523SDave May 196a9cbaee5SMatthew G. Knepley PetscFunctionBegin; 1979566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 19828b400f6SJacob Faibussowitsch PetscCheck(swarm->vec_field_set, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmVectorDefineField first"); 19908401ef6SPierre Jolivet PetscCheck(swarm->vec_field_nlocal == swarm->db->L, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSwarm sizes have changed since last call to VectorDefineField first"); 200cc651181SDave May 2019566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmField_%s", swarm->vec_field_name)); 2029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &x)); 2039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)x, name)); 2049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(x, swarm->db->L * swarm->vec_field_bs, PETSC_DETERMINE)); 2059566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(x, swarm->vec_field_bs)); 2069566063dSJacob Faibussowitsch PetscCall(VecSetDM(x, dm)); 2079566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(x)); 208b5bcf523SDave May *vec = x; 2093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 210b5bcf523SDave May } 211b5bcf523SDave May 212d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec) 213d71ae5a4SJacob Faibussowitsch { 214fb1bcc12SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 21577048351SPatrick Sanan DMSwarmDataField gfield; 2162e956fe4SStefano Zampini PetscInt bs, nlocal, fid = -1, cfid = -2; 2172e956fe4SStefano Zampini PetscBool flg; 218d3a51819SDave May 219fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 2202e956fe4SStefano Zampini /* check vector is an inplace array */ 2212e956fe4SStefano Zampini PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid)); 2222e956fe4SStefano Zampini PetscCall(PetscObjectComposedDataGetInt((PetscObject)*vec, SwarmDataFieldId, cfid, flg)); 223e978a55eSPierre 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); 2249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(*vec, &nlocal)); 2259566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(*vec, &bs)); 22608401ef6SPierre 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"); 2279566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 2289566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldRestoreAccess(gfield)); 2298df78e51SMark Adams PetscCall(VecResetArray(*vec)); 2309566063dSJacob Faibussowitsch PetscCall(VecDestroy(vec)); 2313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 232fb1bcc12SMatthew G. Knepley } 233fb1bcc12SMatthew G. Knepley 234d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec) 235d71ae5a4SJacob Faibussowitsch { 236fb1bcc12SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 237fb1bcc12SMatthew G. Knepley PetscDataType type; 238fb1bcc12SMatthew G. Knepley PetscScalar *array; 2392e956fe4SStefano Zampini PetscInt bs, n, fid; 240fb1bcc12SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 241e4fbd051SBarry Smith PetscMPIInt size; 2428df78e51SMark Adams PetscBool iscuda, iskokkos; 243fb1bcc12SMatthew G. Knepley 244fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 2459566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 2469566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL)); 2479566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, fieldname, &bs, &type, (void **)&array)); 24808401ef6SPierre Jolivet PetscCheck(type == PETSC_REAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL"); 249fb1bcc12SMatthew G. Knepley 2509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 2518df78e51SMark Adams PetscCall(PetscStrcmp(dm->vectype, VECKOKKOS, &iskokkos)); 2528df78e51SMark Adams PetscCall(PetscStrcmp(dm->vectype, VECCUDA, &iscuda)); 2538df78e51SMark Adams PetscCall(VecCreate(comm, vec)); 2548df78e51SMark Adams PetscCall(VecSetSizes(*vec, n * bs, PETSC_DETERMINE)); 2558df78e51SMark Adams PetscCall(VecSetBlockSize(*vec, bs)); 2568df78e51SMark Adams if (iskokkos) PetscCall(VecSetType(*vec, VECKOKKOS)); 2578df78e51SMark Adams else if (iscuda) PetscCall(VecSetType(*vec, VECCUDA)); 2588df78e51SMark Adams else PetscCall(VecSetType(*vec, VECSTANDARD)); 2598df78e51SMark Adams PetscCall(VecPlaceArray(*vec, array)); 2608df78e51SMark Adams 2619566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN - 1, "DMSwarmSharedField_%s", fieldname)); 2629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*vec, name)); 263fb1bcc12SMatthew G. Knepley 264fb1bcc12SMatthew G. Knepley /* Set guard */ 2652e956fe4SStefano Zampini PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldIdByName(swarm->db, fieldname, &fid)); 2662e956fe4SStefano Zampini PetscCall(PetscObjectComposedDataSetInt((PetscObject)*vec, SwarmDataFieldId, fid)); 26774d0cae8SMatthew G. Knepley 2689566063dSJacob Faibussowitsch PetscCall(VecSetDM(*vec, dm)); 2699566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Swarm)); 2703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 271fb1bcc12SMatthew G. Knepley } 272fb1bcc12SMatthew G. Knepley 2730643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by 2740643ed39SMatthew G. Knepley 2750643ed39SMatthew G. Knepley \hat f = \sum_i f_i \phi_i 2760643ed39SMatthew G. Knepley 2770643ed39SMatthew G. Knepley and a particle function is given by 2780643ed39SMatthew G. Knepley 2790643ed39SMatthew G. Knepley f = \sum_i w_i \delta(x - x_i) 2800643ed39SMatthew G. Knepley 2810643ed39SMatthew G. Knepley then we want to require that 2820643ed39SMatthew G. Knepley 2830643ed39SMatthew G. Knepley M \hat f = M_p f 2840643ed39SMatthew G. Knepley 2850643ed39SMatthew G. Knepley where the particle mass matrix is given by 2860643ed39SMatthew G. Knepley 2870643ed39SMatthew G. Knepley (M_p)_{ij} = \int \phi_i \delta(x - x_j) 2880643ed39SMatthew G. Knepley 2890643ed39SMatthew G. Knepley The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in 2900643ed39SMatthew G. Knepley his integral. We allow this with the boolean flag. 2910643ed39SMatthew G. Knepley */ 292d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) 293d71ae5a4SJacob Faibussowitsch { 29483c47955SMatthew G. Knepley const char *name = "Mass Matrix"; 2950643ed39SMatthew G. Knepley MPI_Comm comm; 29683c47955SMatthew G. Knepley PetscDS prob; 29783c47955SMatthew G. Knepley PetscSection fsection, globalFSection; 298e8f14785SLisandro Dalcin PetscHSetIJ ht; 2990643ed39SMatthew G. Knepley PetscLayout rLayout, colLayout; 30083c47955SMatthew G. Knepley PetscInt *dnz, *onz; 301adb2528bSMark Adams PetscInt locRows, locCols, rStart, colStart, colEnd, *rowIDXs; 3020643ed39SMatthew G. Knepley PetscReal *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0}; 30383c47955SMatthew G. Knepley PetscScalar *elemMat; 3040bf7c1c5SMatthew G. Knepley PetscInt dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0, totNc = 0; 30583c47955SMatthew G. Knepley 30683c47955SMatthew G. Knepley PetscFunctionBegin; 3079566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mass, &comm)); 3089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmf, &dim)); 3099566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmf, &prob)); 3109566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 3119566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim)); 3129566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(dim, &v0, dim * dim, &J, dim * dim, &invJ)); 3139566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection)); 3149566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 3159566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd)); 3169566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mass, &locRows, &locCols)); 31783c47955SMatthew G. Knepley 3189566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &colLayout)); 3199566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(colLayout, locCols)); 3209566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(colLayout, 1)); 3219566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colLayout)); 3229566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd)); 3239566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&colLayout)); 3240643ed39SMatthew G. Knepley 3259566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 3269566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 3279566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 3289566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 3299566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL)); 3309566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 3310643ed39SMatthew G. Knepley 3329566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz)); 3339566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&ht)); 33453e60ab4SJoseph Pusztay 3359566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(comm, NULL)); 3360bf7c1c5SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 3370bf7c1c5SMatthew G. Knepley PetscObject obj; 3380bf7c1c5SMatthew G. Knepley PetscClassId id; 3390bf7c1c5SMatthew G. Knepley PetscInt Nc; 3400bf7c1c5SMatthew G. Knepley 3410bf7c1c5SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 3420bf7c1c5SMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 3430bf7c1c5SMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 3440bf7c1c5SMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 3450bf7c1c5SMatthew G. Knepley totNc += Nc; 3460bf7c1c5SMatthew G. Knepley } 3470643ed39SMatthew G. Knepley /* count non-zeros */ 3489566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(dmc)); 34983c47955SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 3500bf7c1c5SMatthew G. Knepley PetscObject obj; 3510bf7c1c5SMatthew G. Knepley PetscClassId id; 3520bf7c1c5SMatthew G. Knepley PetscInt Nc; 3530bf7c1c5SMatthew G. Knepley 3540bf7c1c5SMatthew G. Knepley PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 3550bf7c1c5SMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 3560bf7c1c5SMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 3570bf7c1c5SMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 3580bf7c1c5SMatthew G. Knepley 35983c47955SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 3600643ed39SMatthew G. Knepley PetscInt *findices, *cindices; /* fine is vertices, coarse is particles */ 36183c47955SMatthew G. Knepley PetscInt numFIndices, numCIndices; 36283c47955SMatthew G. Knepley 3639566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 3649566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 365fc7c92abSMatthew G. Knepley maxC = PetscMax(maxC, numCIndices); 36683c47955SMatthew G. Knepley { 367e8f14785SLisandro Dalcin PetscHashIJKey key; 368e8f14785SLisandro Dalcin PetscBool missing; 3690bf7c1c5SMatthew G. Knepley for (PetscInt i = 0; i < numFIndices; ++i) { 370adb2528bSMark Adams key.j = findices[i]; /* global column (from Plex) */ 371adb2528bSMark Adams if (key.j >= 0) { 37283c47955SMatthew G. Knepley /* Get indices for coarse elements */ 3730bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) { 3740bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 3750bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle here 3760bf7c1c5SMatthew G. Knepley key.i = cindices[j] * totNc + c + rStart; /* global cols (from Swarm) */ 377adb2528bSMark Adams if (key.i < 0) continue; 3789566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(ht, key, &missing)); 37983c47955SMatthew G. Knepley if (missing) { 3800643ed39SMatthew G. Knepley if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart]; 381e8f14785SLisandro Dalcin else ++onz[key.i - rStart]; 38263a3b9bcSJacob Faibussowitsch } else SETERRQ(PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Set new value at %" PetscInt_FMT ",%" PetscInt_FMT, key.i, key.j); 38383c47955SMatthew G. Knepley } 384fc7c92abSMatthew G. Knepley } 385fc7c92abSMatthew G. Knepley } 3860bf7c1c5SMatthew G. Knepley } 3879566063dSJacob Faibussowitsch PetscCall(PetscFree(cindices)); 38883c47955SMatthew G. Knepley } 3899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 39083c47955SMatthew G. Knepley } 39183c47955SMatthew G. Knepley } 3929566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&ht)); 3939566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL)); 3949566063dSJacob Faibussowitsch PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 3959566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnz, onz)); 3960bf7c1c5SMatthew G. Knepley PetscCall(PetscMalloc3(maxC * totNc * totDim, &elemMat, maxC * totNc, &rowIDXs, maxC * dim, &xi)); 39783c47955SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 398ef0bb6c7SMatthew G. Knepley PetscTabulation Tcoarse; 39983c47955SMatthew G. Knepley PetscObject obj; 400ad9634fcSMatthew G. Knepley PetscClassId id; 401ea7032a0SMatthew G. Knepley PetscReal *fieldVals; 4020bf7c1c5SMatthew G. Knepley PetscInt Nc; 40383c47955SMatthew G. Knepley 4049566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 405ad9634fcSMatthew G. Knepley PetscCall(PetscObjectGetClassId(obj, &id)); 406ad9634fcSMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 407ad9634fcSMatthew G. Knepley else PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 408ea7032a0SMatthew G. Knepley 409ea7032a0SMatthew G. Knepley PetscCall(DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&fieldVals)); 41083c47955SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 41183c47955SMatthew G. Knepley PetscInt *findices, *cindices; 41283c47955SMatthew G. Knepley PetscInt numFIndices, numCIndices; 41383c47955SMatthew G. Knepley 4140643ed39SMatthew G. Knepley /* TODO: Use DMField instead of assuming affine */ 4159566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ)); 4169566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 4179566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 4180bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &fieldVals[cindices[j] * dim], &xi[j * dim]); 419ad9634fcSMatthew G. Knepley if (id == PETSCFE_CLASSID) PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse)); 420ad9634fcSMatthew G. Knepley else PetscCall(PetscFVCreateTabulation((PetscFV)obj, 1, numCIndices, xi, 0, &Tcoarse)); 42183c47955SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 4220bf7c1c5SMatthew G. Knepley PetscCall(PetscArrayzero(elemMat, numCIndices * Nc * totDim)); 4230bf7c1c5SMatthew G. Knepley for (PetscInt i = 0; i < numFIndices / Nc; ++i) { 4240bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) { 4250bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 4260bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle and field here 4270643ed39SMatthew G. Knepley /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */ 4280bf7c1c5SMatthew G. Knepley elemMat[(j * totNc + c) * numFIndices + i * Nc + c] += Tcoarse->T[0][(j * numFIndices + i * Nc + c) * Nc + c] * (useDeltaFunction ? 1.0 : detJ); 42983c47955SMatthew G. Knepley } 4300643ed39SMatthew G. Knepley } 4310643ed39SMatthew G. Knepley } 4320bf7c1c5SMatthew G. Knepley for (PetscInt j = 0; j < numCIndices; ++j) 4330bf7c1c5SMatthew G. Knepley // TODO Need field offset on particle here 4340bf7c1c5SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) rowIDXs[j * Nc + c] = cindices[j] * totNc + c + rStart; 4350bf7c1c5SMatthew G. Knepley if (0) PetscCall(DMPrintCellMatrix(cell, name, numCIndices * Nc, numFIndices, elemMat)); 4360bf7c1c5SMatthew G. Knepley PetscCall(MatSetValues(mass, numCIndices * Nc, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES)); 4379566063dSJacob Faibussowitsch PetscCall(PetscFree(cindices)); 4389566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 4399566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tcoarse)); 44083c47955SMatthew G. Knepley } 441ea7032a0SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&fieldVals)); 44283c47955SMatthew G. Knepley } 4439566063dSJacob Faibussowitsch PetscCall(PetscFree3(elemMat, rowIDXs, xi)); 4449566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(dmc)); 4459566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ)); 4469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY)); 4479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY)); 4483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44983c47955SMatthew G. Knepley } 45083c47955SMatthew G. Knepley 451d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */ 452d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat *m) 453d71ae5a4SJacob Faibussowitsch { 454d0c080abSJoseph Pusztay Vec field; 455d0c080abSJoseph Pusztay PetscInt size; 456d0c080abSJoseph Pusztay 457d0c080abSJoseph Pusztay PetscFunctionBegin; 4589566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(sw, &field)); 4599566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(field, &size)); 4609566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(sw, &field)); 4619566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, m)); 4629566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(*m)); 4639566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size)); 4649566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(*m, 1, NULL)); 4659566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(*m)); 4669566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY)); 4679566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY)); 4689566063dSJacob Faibussowitsch PetscCall(MatShift(*m, 1.0)); 4699566063dSJacob Faibussowitsch PetscCall(MatSetDM(*m, sw)); 4703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 471d0c080abSJoseph Pusztay } 472d0c080abSJoseph Pusztay 473adb2528bSMark Adams /* FEM cols, Particle rows */ 474d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass) 475d71ae5a4SJacob Faibussowitsch { 476895a1698SMatthew G. Knepley PetscSection gsf; 4770bf7c1c5SMatthew G. Knepley PetscInt m, n, Np, bs = 1; 47883c47955SMatthew G. Knepley void *ctx; 4790bf7c1c5SMatthew G. Knepley PetscBool set = ((DM_Swarm *)dmCoarse->data)->vec_field_set; 4800bf7c1c5SMatthew G. Knepley char *name = ((DM_Swarm *)dmCoarse->data)->vec_field_name; 48183c47955SMatthew G. Knepley 48283c47955SMatthew G. Knepley PetscFunctionBegin; 4839566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmFine, &gsf)); 4849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m)); 4850bf7c1c5SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(dmCoarse, &Np)); 4860bf7c1c5SMatthew G. Knepley // TODO Include all fields 4870bf7c1c5SMatthew G. Knepley if (set) PetscCall(DMSwarmGetFieldInfo(dmCoarse, name, &bs, NULL)); 4880bf7c1c5SMatthew G. Knepley n = Np * bs; 4899566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 4909566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE)); 4919566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 4929566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 49383c47955SMatthew G. Knepley 4949566063dSJacob Faibussowitsch PetscCall(DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx)); 4959566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view")); 4963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49783c47955SMatthew G. Knepley } 49883c47955SMatthew G. Knepley 499d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx) 500d71ae5a4SJacob Faibussowitsch { 5014cc7f7b2SMatthew G. Knepley const char *name = "Mass Matrix Square"; 5024cc7f7b2SMatthew G. Knepley MPI_Comm comm; 5034cc7f7b2SMatthew G. Knepley PetscDS prob; 5044cc7f7b2SMatthew G. Knepley PetscSection fsection, globalFSection; 5054cc7f7b2SMatthew G. Knepley PetscHSetIJ ht; 5064cc7f7b2SMatthew G. Knepley PetscLayout rLayout, colLayout; 5074cc7f7b2SMatthew G. Knepley PetscInt *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize; 5084cc7f7b2SMatthew G. Knepley PetscInt locRows, locCols, rStart, colStart, colEnd, *rowIDXs; 5094cc7f7b2SMatthew G. Knepley PetscReal *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0}; 5104cc7f7b2SMatthew G. Knepley PetscScalar *elemMat, *elemMatSq; 5114cc7f7b2SMatthew G. Knepley PetscInt cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0; 5124cc7f7b2SMatthew G. Knepley 5134cc7f7b2SMatthew G. Knepley PetscFunctionBegin; 5149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mass, &comm)); 5159566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmf, &cdim)); 5169566063dSJacob Faibussowitsch PetscCall(DMGetDS(dmf, &prob)); 5179566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(prob, &Nf)); 5189566063dSJacob Faibussowitsch PetscCall(PetscDSGetTotalDimension(prob, &totDim)); 5199566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(cdim, &v0, cdim * cdim, &J, cdim * cdim, &invJ)); 5209566063dSJacob Faibussowitsch PetscCall(DMGetLocalSection(dmf, &fsection)); 5219566063dSJacob Faibussowitsch PetscCall(DMGetGlobalSection(dmf, &globalFSection)); 5229566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd)); 5239566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mass, &locRows, &locCols)); 5244cc7f7b2SMatthew G. Knepley 5259566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &colLayout)); 5269566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(colLayout, locCols)); 5279566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(colLayout, 1)); 5289566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(colLayout)); 5299566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(colLayout, &colStart, &colEnd)); 5309566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&colLayout)); 5314cc7f7b2SMatthew G. Knepley 5329566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(comm, &rLayout)); 5339566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(rLayout, locRows)); 5349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(rLayout, 1)); 5359566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(rLayout)); 5369566063dSJacob Faibussowitsch PetscCall(PetscLayoutGetRange(rLayout, &rStart, NULL)); 5379566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&rLayout)); 5384cc7f7b2SMatthew G. Knepley 5399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dmf, &depth)); 5409566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize)); 5414cc7f7b2SMatthew G. Knepley maxAdjSize = PetscPowInt(maxConeSize * maxSupportSize, depth); 5429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxAdjSize, &adj)); 5434cc7f7b2SMatthew G. Knepley 5449566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(locRows, &dnz, locRows, &onz)); 5459566063dSJacob Faibussowitsch PetscCall(PetscHSetIJCreate(&ht)); 5464cc7f7b2SMatthew G. Knepley /* Count nonzeros 5474cc7f7b2SMatthew G. Knepley This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous 5484cc7f7b2SMatthew G. Knepley */ 5499566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(dmc)); 5504cc7f7b2SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 5514cc7f7b2SMatthew G. Knepley PetscInt i; 5524cc7f7b2SMatthew G. Knepley PetscInt *cindices; 5534cc7f7b2SMatthew G. Knepley PetscInt numCIndices; 5544cc7f7b2SMatthew G. Knepley #if 0 5554cc7f7b2SMatthew G. Knepley PetscInt adjSize = maxAdjSize, a, j; 5564cc7f7b2SMatthew G. Knepley #endif 5574cc7f7b2SMatthew G. Knepley 5589566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 5594cc7f7b2SMatthew G. Knepley maxC = PetscMax(maxC, numCIndices); 5604cc7f7b2SMatthew G. Knepley /* Diagonal block */ 561ad540459SPierre Jolivet for (i = 0; i < numCIndices; ++i) dnz[cindices[i]] += numCIndices; 5624cc7f7b2SMatthew G. Knepley #if 0 5634cc7f7b2SMatthew G. Knepley /* Off-diagonal blocks */ 5649566063dSJacob Faibussowitsch PetscCall(DMPlexGetAdjacency(dmf, cell, &adjSize, &adj)); 5654cc7f7b2SMatthew G. Knepley for (a = 0; a < adjSize; ++a) { 5664cc7f7b2SMatthew G. Knepley if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) { 5674cc7f7b2SMatthew G. Knepley const PetscInt ncell = adj[a]; 5684cc7f7b2SMatthew G. Knepley PetscInt *ncindices; 5694cc7f7b2SMatthew G. Knepley PetscInt numNCIndices; 5704cc7f7b2SMatthew G. Knepley 5719566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices)); 5724cc7f7b2SMatthew G. Knepley { 5734cc7f7b2SMatthew G. Knepley PetscHashIJKey key; 5744cc7f7b2SMatthew G. Knepley PetscBool missing; 5754cc7f7b2SMatthew G. Knepley 5764cc7f7b2SMatthew G. Knepley for (i = 0; i < numCIndices; ++i) { 5774cc7f7b2SMatthew G. Knepley key.i = cindices[i] + rStart; /* global rows (from Swarm) */ 5784cc7f7b2SMatthew G. Knepley if (key.i < 0) continue; 5794cc7f7b2SMatthew G. Knepley for (j = 0; j < numNCIndices; ++j) { 5804cc7f7b2SMatthew G. Knepley key.j = ncindices[j] + rStart; /* global column (from Swarm) */ 5814cc7f7b2SMatthew G. Knepley if (key.j < 0) continue; 5829566063dSJacob Faibussowitsch PetscCall(PetscHSetIJQueryAdd(ht, key, &missing)); 5834cc7f7b2SMatthew G. Knepley if (missing) { 5844cc7f7b2SMatthew G. Knepley if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart]; 5854cc7f7b2SMatthew G. Knepley else ++onz[key.i - rStart]; 5864cc7f7b2SMatthew G. Knepley } 5874cc7f7b2SMatthew G. Knepley } 5884cc7f7b2SMatthew G. Knepley } 5894cc7f7b2SMatthew G. Knepley } 5909566063dSJacob Faibussowitsch PetscCall(PetscFree(ncindices)); 5914cc7f7b2SMatthew G. Knepley } 5924cc7f7b2SMatthew G. Knepley } 5934cc7f7b2SMatthew G. Knepley #endif 5949566063dSJacob Faibussowitsch PetscCall(PetscFree(cindices)); 5954cc7f7b2SMatthew G. Knepley } 5969566063dSJacob Faibussowitsch PetscCall(PetscHSetIJDestroy(&ht)); 5979566063dSJacob Faibussowitsch PetscCall(MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL)); 5989566063dSJacob Faibussowitsch PetscCall(MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 5999566063dSJacob Faibussowitsch PetscCall(PetscFree2(dnz, onz)); 6009566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(maxC * totDim, &elemMat, maxC * maxC, &elemMatSq, maxC, &rowIDXs, maxC * cdim, &xi)); 6014cc7f7b2SMatthew G. Knepley /* Fill in values 6024cc7f7b2SMatthew G. Knepley Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q) 6034cc7f7b2SMatthew G. Knepley Start just by producing block diagonal 6044cc7f7b2SMatthew G. Knepley Could loop over adjacent cells 6054cc7f7b2SMatthew G. Knepley Produce neighboring element matrix 6064cc7f7b2SMatthew G. Knepley TODO Determine which columns and rows correspond to shared dual vector 6074cc7f7b2SMatthew G. Knepley Do MatMatMult with rectangular matrices 6084cc7f7b2SMatthew G. Knepley Insert block 6094cc7f7b2SMatthew G. Knepley */ 6104cc7f7b2SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 6114cc7f7b2SMatthew G. Knepley PetscTabulation Tcoarse; 6124cc7f7b2SMatthew G. Knepley PetscObject obj; 6134cc7f7b2SMatthew G. Knepley PetscReal *coords; 6144cc7f7b2SMatthew G. Knepley PetscInt Nc, i; 6154cc7f7b2SMatthew G. Knepley 6169566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(prob, field, &obj)); 6179566063dSJacob Faibussowitsch PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 61863a3b9bcSJacob Faibussowitsch PetscCheck(Nc == 1, PetscObjectComm((PetscObject)dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %" PetscInt_FMT, Nc); 6199566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 6204cc7f7b2SMatthew G. Knepley for (cell = cStart; cell < cEnd; ++cell) { 6214cc7f7b2SMatthew G. Knepley PetscInt *findices, *cindices; 6224cc7f7b2SMatthew G. Knepley PetscInt numFIndices, numCIndices; 6234cc7f7b2SMatthew G. Knepley PetscInt p, c; 6244cc7f7b2SMatthew G. Knepley 6254cc7f7b2SMatthew G. Knepley /* TODO: Use DMField instead of assuming affine */ 6269566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ)); 6279566063dSJacob Faibussowitsch PetscCall(DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 6289566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices)); 629ad540459SPierre Jolivet for (p = 0; p < numCIndices; ++p) CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p] * cdim], &xi[p * cdim]); 6309566063dSJacob Faibussowitsch PetscCall(PetscFECreateTabulation((PetscFE)obj, 1, numCIndices, xi, 0, &Tcoarse)); 6314cc7f7b2SMatthew G. Knepley /* Get elemMat entries by multiplying by weight */ 6329566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(elemMat, numCIndices * totDim)); 6334cc7f7b2SMatthew G. Knepley for (i = 0; i < numFIndices; ++i) { 6344cc7f7b2SMatthew G. Knepley for (p = 0; p < numCIndices; ++p) { 6354cc7f7b2SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 6364cc7f7b2SMatthew G. Knepley /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */ 6374cc7f7b2SMatthew G. Knepley elemMat[p * numFIndices + i] += Tcoarse->T[0][(p * numFIndices + i) * Nc + c] * (useDeltaFunction ? 1.0 : detJ); 6384cc7f7b2SMatthew G. Knepley } 6394cc7f7b2SMatthew G. Knepley } 6404cc7f7b2SMatthew G. Knepley } 6419566063dSJacob Faibussowitsch PetscCall(PetscTabulationDestroy(&Tcoarse)); 6424cc7f7b2SMatthew G. Knepley for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart; 6439566063dSJacob Faibussowitsch if (0) PetscCall(DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat)); 6444cc7f7b2SMatthew G. Knepley /* Block diagonal */ 64578884ca7SMatthew G. Knepley if (numCIndices) { 6464cc7f7b2SMatthew G. Knepley PetscBLASInt blasn, blask; 6474cc7f7b2SMatthew G. Knepley PetscScalar one = 1.0, zero = 0.0; 6484cc7f7b2SMatthew G. Knepley 6499566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(numCIndices, &blasn)); 6509566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(numFIndices, &blask)); 651792fecdfSBarry Smith PetscCallBLAS("BLASgemm", BLASgemm_("T", "N", &blasn, &blasn, &blask, &one, elemMat, &blask, elemMat, &blask, &zero, elemMatSq, &blasn)); 6524cc7f7b2SMatthew G. Knepley } 6539566063dSJacob Faibussowitsch PetscCall(MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES)); 6544cf0e950SBarry Smith /* TODO off-diagonal */ 6559566063dSJacob Faibussowitsch PetscCall(PetscFree(cindices)); 6569566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL)); 6574cc7f7b2SMatthew G. Knepley } 6589566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 6594cc7f7b2SMatthew G. Knepley } 6609566063dSJacob Faibussowitsch PetscCall(PetscFree4(elemMat, elemMatSq, rowIDXs, xi)); 6619566063dSJacob Faibussowitsch PetscCall(PetscFree(adj)); 6629566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(dmc)); 6639566063dSJacob Faibussowitsch PetscCall(PetscFree3(v0, J, invJ)); 6649566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY)); 6659566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY)); 6663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6674cc7f7b2SMatthew G. Knepley } 6684cc7f7b2SMatthew G. Knepley 669cc4c1da9SBarry Smith /*@ 6704cc7f7b2SMatthew G. Knepley DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p 6714cc7f7b2SMatthew G. Knepley 67220f4b53cSBarry Smith Collective 6734cc7f7b2SMatthew G. Knepley 67460225df5SJacob Faibussowitsch Input Parameters: 67520f4b53cSBarry Smith + dmCoarse - a `DMSWARM` 67620f4b53cSBarry Smith - dmFine - a `DMPLEX` 6774cc7f7b2SMatthew G. Knepley 67860225df5SJacob Faibussowitsch Output Parameter: 6794cc7f7b2SMatthew G. Knepley . mass - the square of the particle mass matrix 6804cc7f7b2SMatthew G. Knepley 6814cc7f7b2SMatthew G. Knepley Level: advanced 6824cc7f7b2SMatthew G. Knepley 68320f4b53cSBarry Smith Note: 6844cc7f7b2SMatthew G. Knepley We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the 6854cc7f7b2SMatthew G. Knepley future to compute the full normal equations. 6864cc7f7b2SMatthew G. Knepley 68720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMCreateMassMatrix()` 6884cc7f7b2SMatthew G. Knepley @*/ 689d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass) 690d71ae5a4SJacob Faibussowitsch { 6914cc7f7b2SMatthew G. Knepley PetscInt n; 6924cc7f7b2SMatthew G. Knepley void *ctx; 6934cc7f7b2SMatthew G. Knepley 6944cc7f7b2SMatthew G. Knepley PetscFunctionBegin; 6959566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dmCoarse, &n)); 6969566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass)); 6979566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE)); 6989566063dSJacob Faibussowitsch PetscCall(MatSetType(*mass, dmCoarse->mattype)); 6999566063dSJacob Faibussowitsch PetscCall(DMGetApplicationContext(dmFine, &ctx)); 7004cc7f7b2SMatthew G. Knepley 7019566063dSJacob Faibussowitsch PetscCall(DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx)); 7029566063dSJacob Faibussowitsch PetscCall(MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view")); 7033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7044cc7f7b2SMatthew G. Knepley } 7054cc7f7b2SMatthew G. Knepley 706cc4c1da9SBarry Smith /*@ 70720f4b53cSBarry Smith DMSwarmCreateGlobalVectorFromField - Creates a `Vec` object sharing the array associated with a given field 708d3a51819SDave May 70920f4b53cSBarry Smith Collective 710d3a51819SDave May 71160225df5SJacob Faibussowitsch Input Parameters: 71220f4b53cSBarry Smith + dm - a `DMSWARM` 71362741f57SDave May - fieldname - the textual name given to a registered field 714d3a51819SDave May 71560225df5SJacob Faibussowitsch Output Parameter: 716d3a51819SDave May . vec - the vector 717d3a51819SDave May 718d3a51819SDave May Level: beginner 719d3a51819SDave May 720cc4c1da9SBarry Smith Note: 72120f4b53cSBarry Smith The vector must be returned using a matching call to `DMSwarmDestroyGlobalVectorFromField()`. 7228b8a3813SDave May 72320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyGlobalVectorFromField()` 724d3a51819SDave May @*/ 725d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) 726d71ae5a4SJacob Faibussowitsch { 727fb1bcc12SMatthew G. Knepley MPI_Comm comm = PetscObjectComm((PetscObject)dm); 728b5bcf523SDave May 729fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 730ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 7319566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec)); 7323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 733b5bcf523SDave May } 734b5bcf523SDave May 735cc4c1da9SBarry Smith /*@ 73620f4b53cSBarry Smith DMSwarmDestroyGlobalVectorFromField - Destroys the `Vec` object which share the array associated with a given field 737d3a51819SDave May 73820f4b53cSBarry Smith Collective 739d3a51819SDave May 74060225df5SJacob Faibussowitsch Input Parameters: 74120f4b53cSBarry Smith + dm - a `DMSWARM` 74262741f57SDave May - fieldname - the textual name given to a registered field 743d3a51819SDave May 74460225df5SJacob Faibussowitsch Output Parameter: 745d3a51819SDave May . vec - the vector 746d3a51819SDave May 747d3a51819SDave May Level: beginner 748d3a51819SDave May 74920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateGlobalVectorFromField()` 750d3a51819SDave May @*/ 751d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm, const char fieldname[], Vec *vec) 752d71ae5a4SJacob Faibussowitsch { 753fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 754ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 7559566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec)); 7563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 757b5bcf523SDave May } 758b5bcf523SDave May 759cc4c1da9SBarry Smith /*@ 76020f4b53cSBarry Smith DMSwarmCreateLocalVectorFromField - Creates a `Vec` object sharing the array associated with a given field 761fb1bcc12SMatthew G. Knepley 76220f4b53cSBarry Smith Collective 763fb1bcc12SMatthew G. Knepley 76460225df5SJacob Faibussowitsch Input Parameters: 76520f4b53cSBarry Smith + dm - a `DMSWARM` 76662741f57SDave May - fieldname - the textual name given to a registered field 767fb1bcc12SMatthew G. Knepley 76860225df5SJacob Faibussowitsch Output Parameter: 769fb1bcc12SMatthew G. Knepley . vec - the vector 770fb1bcc12SMatthew G. Knepley 771fb1bcc12SMatthew G. Knepley Level: beginner 772fb1bcc12SMatthew G. Knepley 77320f4b53cSBarry Smith Note: 7748b8a3813SDave May The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField(). 7758b8a3813SDave May 77620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmDestroyLocalVectorFromField()` 777fb1bcc12SMatthew G. Knepley @*/ 778d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) 779d71ae5a4SJacob Faibussowitsch { 780fb1bcc12SMatthew G. Knepley MPI_Comm comm = PETSC_COMM_SELF; 781bbe8250bSMatthew G. Knepley 782fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 7839566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec)); 7843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 785bbe8250bSMatthew G. Knepley } 786fb1bcc12SMatthew G. Knepley 787cc4c1da9SBarry Smith /*@ 78820f4b53cSBarry Smith DMSwarmDestroyLocalVectorFromField - Destroys the `Vec` object which share the array associated with a given field 789fb1bcc12SMatthew G. Knepley 79020f4b53cSBarry Smith Collective 791fb1bcc12SMatthew G. Knepley 79260225df5SJacob Faibussowitsch Input Parameters: 79320f4b53cSBarry Smith + dm - a `DMSWARM` 79462741f57SDave May - fieldname - the textual name given to a registered field 795fb1bcc12SMatthew G. Knepley 79660225df5SJacob Faibussowitsch Output Parameter: 797fb1bcc12SMatthew G. Knepley . vec - the vector 798fb1bcc12SMatthew G. Knepley 799fb1bcc12SMatthew G. Knepley Level: beginner 800fb1bcc12SMatthew G. Knepley 80120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmCreateLocalVectorFromField()` 802fb1bcc12SMatthew G. Knepley @*/ 803d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm, const char fieldname[], Vec *vec) 804d71ae5a4SJacob Faibussowitsch { 805fb1bcc12SMatthew G. Knepley PetscFunctionBegin; 806ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 8079566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec)); 8083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 809bbe8250bSMatthew G. Knepley } 810bbe8250bSMatthew G. Knepley 811cc4c1da9SBarry Smith /*@ 81220f4b53cSBarry Smith DMSwarmInitializeFieldRegister - Initiates the registration of fields to a `DMSWARM` 813d3a51819SDave May 81420f4b53cSBarry Smith Collective 815d3a51819SDave May 81660225df5SJacob Faibussowitsch Input Parameter: 81720f4b53cSBarry Smith . dm - a `DMSWARM` 818d3a51819SDave May 819d3a51819SDave May Level: beginner 820d3a51819SDave May 82120f4b53cSBarry Smith Note: 82220f4b53cSBarry Smith After all fields have been registered, you must call `DMSwarmFinalizeFieldRegister()`. 823d3a51819SDave May 82420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmFinalizeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`, 825db781477SPatrick Sanan `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 826d3a51819SDave May @*/ 827d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeFieldRegister(DM dm) 828d71ae5a4SJacob Faibussowitsch { 8295f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 8303454631fSDave May 831521f74f9SMatthew G. Knepley PetscFunctionBegin; 832cc651181SDave May if (!swarm->field_registration_initialized) { 8335f50eb2eSDave May swarm->field_registration_initialized = PETSC_TRUE; 834da81f932SPierre Jolivet PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_pid, 1, PETSC_INT64)); /* unique identifier */ 8359566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmField_rank, 1, PETSC_INT)); /* used for communication */ 836cc651181SDave May } 8373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8385f50eb2eSDave May } 8395f50eb2eSDave May 84074d0cae8SMatthew G. Knepley /*@ 84120f4b53cSBarry Smith DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a `DMSWARM` 842d3a51819SDave May 84320f4b53cSBarry Smith Collective 844d3a51819SDave May 84560225df5SJacob Faibussowitsch Input Parameter: 84620f4b53cSBarry Smith . dm - a `DMSWARM` 847d3a51819SDave May 848d3a51819SDave May Level: beginner 849d3a51819SDave May 85020f4b53cSBarry Smith Note: 85120f4b53cSBarry Smith After `DMSwarmFinalizeFieldRegister()` has been called, no new fields can be defined on the `DMSWARM`. 852d3a51819SDave May 85320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmInitializeFieldRegister()`, `DMSwarmRegisterPetscDatatypeField()`, 854db781477SPatrick Sanan `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 855d3a51819SDave May @*/ 856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm) 857d71ae5a4SJacob Faibussowitsch { 8585f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 8596845f8f5SDave May 860521f74f9SMatthew G. Knepley PetscFunctionBegin; 86148a46eb9SPierre Jolivet if (!swarm->field_registration_finalized) PetscCall(DMSwarmDataBucketFinalize(swarm->db)); 862f0cdbbbaSDave May swarm->field_registration_finalized = PETSC_TRUE; 8633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8645f50eb2eSDave May } 8655f50eb2eSDave May 86674d0cae8SMatthew G. Knepley /*@ 86720f4b53cSBarry Smith DMSwarmSetLocalSizes - Sets the length of all registered fields on the `DMSWARM` 868d3a51819SDave May 86920f4b53cSBarry Smith Not Collective 870d3a51819SDave May 87160225df5SJacob Faibussowitsch Input Parameters: 87220f4b53cSBarry Smith + dm - a `DMSWARM` 873d3a51819SDave May . nlocal - the length of each registered field 87462741f57SDave May - buffer - the length of the buffer used to efficient dynamic re-sizing 875d3a51819SDave May 876d3a51819SDave May Level: beginner 877d3a51819SDave May 87820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()` 879d3a51819SDave May @*/ 880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetLocalSizes(DM dm, PetscInt nlocal, PetscInt buffer) 881d71ae5a4SJacob Faibussowitsch { 8825f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 8835f50eb2eSDave May 884521f74f9SMatthew G. Knepley PetscFunctionBegin; 8859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_SetSizes, 0, 0, 0, 0)); 8869566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, buffer)); 8879566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_SetSizes, 0, 0, 0, 0)); 8883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8895f50eb2eSDave May } 8905f50eb2eSDave May 89174d0cae8SMatthew G. Knepley /*@ 89220f4b53cSBarry Smith DMSwarmSetCellDM - Attaches a `DM` to a `DMSWARM` 893d3a51819SDave May 89420f4b53cSBarry Smith Collective 895d3a51819SDave May 89660225df5SJacob Faibussowitsch Input Parameters: 89720f4b53cSBarry Smith + dm - a `DMSWARM` 89820f4b53cSBarry Smith - dmcell - the `DM` to attach to the `DMSWARM` 899d3a51819SDave May 900d3a51819SDave May Level: beginner 901d3a51819SDave May 90220f4b53cSBarry Smith Note: 90320f4b53cSBarry Smith The attached `DM` (dmcell) will be queried for point location and 90420f4b53cSBarry Smith neighbor MPI-rank information if `DMSwarmMigrate()` is called. 905d3a51819SDave May 90620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmGetCellDM()`, `DMSwarmMigrate()` 907d3a51819SDave May @*/ 908d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetCellDM(DM dm, DM dmcell) 909d71ae5a4SJacob Faibussowitsch { 910b16650c8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 911521f74f9SMatthew G. Knepley 912521f74f9SMatthew G. Knepley PetscFunctionBegin; 913b16650c8SDave May swarm->dmcell = dmcell; 9143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 915b16650c8SDave May } 916b16650c8SDave May 91774d0cae8SMatthew G. Knepley /*@ 91820f4b53cSBarry Smith DMSwarmGetCellDM - Fetches the attached cell `DM` 919d3a51819SDave May 92020f4b53cSBarry Smith Collective 921d3a51819SDave May 92260225df5SJacob Faibussowitsch Input Parameter: 92320f4b53cSBarry Smith . dm - a `DMSWARM` 924d3a51819SDave May 92560225df5SJacob Faibussowitsch Output Parameter: 92620f4b53cSBarry Smith . dmcell - the `DM` which was attached to the `DMSWARM` 927d3a51819SDave May 928d3a51819SDave May Level: beginner 929d3a51819SDave May 93020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()` 931d3a51819SDave May @*/ 932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetCellDM(DM dm, DM *dmcell) 933d71ae5a4SJacob Faibussowitsch { 934fe39f135SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 935521f74f9SMatthew G. Knepley 936521f74f9SMatthew G. Knepley PetscFunctionBegin; 937fe39f135SDave May *dmcell = swarm->dmcell; 9383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 939fe39f135SDave May } 940fe39f135SDave May 94174d0cae8SMatthew G. Knepley /*@ 942d5b43468SJose E. Roman DMSwarmGetLocalSize - Retrieves the local length of fields registered 943d3a51819SDave May 94420f4b53cSBarry Smith Not Collective 945d3a51819SDave May 94660225df5SJacob Faibussowitsch Input Parameter: 94720f4b53cSBarry Smith . dm - a `DMSWARM` 948d3a51819SDave May 94960225df5SJacob Faibussowitsch Output Parameter: 950d3a51819SDave May . nlocal - the length of each registered field 951d3a51819SDave May 952d3a51819SDave May Level: beginner 953d3a51819SDave May 95420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetSize()`, `DMSwarmSetLocalSizes()` 955d3a51819SDave May @*/ 956d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetLocalSize(DM dm, PetscInt *nlocal) 957d71ae5a4SJacob Faibussowitsch { 958dcf43ee8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 959dcf43ee8SDave May 960521f74f9SMatthew G. Knepley PetscFunctionBegin; 9619566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, nlocal, NULL, NULL)); 9623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 963dcf43ee8SDave May } 964dcf43ee8SDave May 96574d0cae8SMatthew G. Knepley /*@ 966d5b43468SJose E. Roman DMSwarmGetSize - Retrieves the total length of fields registered 967d3a51819SDave May 96820f4b53cSBarry Smith Collective 969d3a51819SDave May 97060225df5SJacob Faibussowitsch Input Parameter: 97120f4b53cSBarry Smith . dm - a `DMSWARM` 972d3a51819SDave May 97360225df5SJacob Faibussowitsch Output Parameter: 974d3a51819SDave May . n - the total length of each registered field 975d3a51819SDave May 976d3a51819SDave May Level: beginner 977d3a51819SDave May 978d3a51819SDave May Note: 97920f4b53cSBarry Smith This calls `MPI_Allreduce()` upon each call (inefficient but safe) 980d3a51819SDave May 98120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetLocalSize()`, `DMSwarmSetLocalSizes()` 982d3a51819SDave May @*/ 983d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetSize(DM dm, PetscInt *n) 984d71ae5a4SJacob Faibussowitsch { 985dcf43ee8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 9865627991aSBarry Smith PetscInt nlocal; 987dcf43ee8SDave May 988521f74f9SMatthew G. Knepley PetscFunctionBegin; 9899566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL)); 990712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&nlocal, n, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm))); 9913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 992dcf43ee8SDave May } 993dcf43ee8SDave May 994cc4c1da9SBarry Smith /*@ 99520f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField - Register a field to a `DMSWARM` with a native PETSc data type 996d3a51819SDave May 99720f4b53cSBarry Smith Collective 998d3a51819SDave May 99960225df5SJacob Faibussowitsch Input Parameters: 100020f4b53cSBarry Smith + dm - a `DMSWARM` 1001d3a51819SDave May . fieldname - the textual name to identify this field 1002d3a51819SDave May . blocksize - the number of each data type 100320f4b53cSBarry Smith - type - a valid PETSc data type (`PETSC_CHAR`, `PETSC_SHORT`, `PETSC_INT`, `PETSC_FLOAT`, `PETSC_REAL`, `PETSC_LONG`) 1004d3a51819SDave May 1005d3a51819SDave May Level: beginner 1006d3a51819SDave May 1007d3a51819SDave May Notes: 10088b8a3813SDave May The textual name for each registered field must be unique. 1009d3a51819SDave May 101020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterUserStructField()`, `DMSwarmRegisterUserDatatypeField()` 1011d3a51819SDave May @*/ 1012d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm, const char fieldname[], PetscInt blocksize, PetscDataType type) 1013d71ae5a4SJacob Faibussowitsch { 1014b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1015b62e03f8SDave May size_t size; 1016b62e03f8SDave May 1017521f74f9SMatthew G. Knepley PetscFunctionBegin; 101828b400f6SJacob Faibussowitsch PetscCheck(swarm->field_registration_initialized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Must call DMSwarmInitializeFieldRegister() first"); 101928b400f6SJacob Faibussowitsch PetscCheck(!swarm->field_registration_finalized, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first"); 10205f50eb2eSDave May 102108401ef6SPierre Jolivet PetscCheck(type != PETSC_OBJECT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 102208401ef6SPierre Jolivet PetscCheck(type != PETSC_FUNCTION, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 102308401ef6SPierre Jolivet PetscCheck(type != PETSC_STRING, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 102408401ef6SPierre Jolivet PetscCheck(type != PETSC_STRUCT, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 102508401ef6SPierre Jolivet PetscCheck(type != PETSC_DATATYPE_UNKNOWN, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Valid for {char,short,int,long,float,double}"); 1026b62e03f8SDave May 10279566063dSJacob Faibussowitsch PetscCall(PetscDataTypeGetSize(type, &size)); 1028b62e03f8SDave May /* Load a specific data type into data bucket, specifying textual name and its size in bytes */ 10299566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterPetscDatatypeField", fieldname, blocksize * size, NULL)); 103052c3ed93SDave May { 103177048351SPatrick Sanan DMSwarmDataField gfield; 103252c3ed93SDave May 10339566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 10349566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize)); 103552c3ed93SDave May } 1036b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = type; 10373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1038b62e03f8SDave May } 1039b62e03f8SDave May 1040d3a51819SDave May /*@C 104120f4b53cSBarry Smith DMSwarmRegisterUserStructField - Register a user defined struct to a `DMSWARM` 1042d3a51819SDave May 104320f4b53cSBarry Smith Collective 1044d3a51819SDave May 104560225df5SJacob Faibussowitsch Input Parameters: 104620f4b53cSBarry Smith + dm - a `DMSWARM` 1047d3a51819SDave May . fieldname - the textual name to identify this field 104862741f57SDave May - size - the size in bytes of the user struct of each data type 1049d3a51819SDave May 1050d3a51819SDave May Level: beginner 1051d3a51819SDave May 105220f4b53cSBarry Smith Note: 10538b8a3813SDave May The textual name for each registered field must be unique. 1054d3a51819SDave May 105520f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserDatatypeField()` 1056d3a51819SDave May @*/ 1057d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserStructField(DM dm, const char fieldname[], size_t size) 1058d71ae5a4SJacob Faibussowitsch { 1059b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1060b62e03f8SDave May 1061521f74f9SMatthew G. Knepley PetscFunctionBegin; 10629566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserStructField", fieldname, size, NULL)); 1063b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_STRUCT; 10643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1065b62e03f8SDave May } 1066b62e03f8SDave May 1067d3a51819SDave May /*@C 106820f4b53cSBarry Smith DMSwarmRegisterUserDatatypeField - Register a user defined data type to a `DMSWARM` 1069d3a51819SDave May 107020f4b53cSBarry Smith Collective 1071d3a51819SDave May 107260225df5SJacob Faibussowitsch Input Parameters: 107320f4b53cSBarry Smith + dm - a `DMSWARM` 1074d3a51819SDave May . fieldname - the textual name to identify this field 1075d3a51819SDave May . size - the size in bytes of the user data type 107662741f57SDave May - blocksize - the number of each data type 1077d3a51819SDave May 1078d3a51819SDave May Level: beginner 1079d3a51819SDave May 108020f4b53cSBarry Smith Note: 10818b8a3813SDave May The textual name for each registered field must be unique. 1082d3a51819SDave May 108342747ad1SJacob Faibussowitsch .seealso: `DM`, `DMSWARM`, `DMSwarmRegisterPetscDatatypeField()`, `DMSwarmRegisterUserStructField()` 1084d3a51819SDave May @*/ 1085d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm, const char fieldname[], size_t size, PetscInt blocksize) 1086d71ae5a4SJacob Faibussowitsch { 1087b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1088b62e03f8SDave May 1089521f74f9SMatthew G. Knepley PetscFunctionBegin; 10909566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRegisterField(swarm->db, "DMSwarmRegisterUserDatatypeField", fieldname, blocksize * size, NULL)); 1091320740a0SDave May { 109277048351SPatrick Sanan DMSwarmDataField gfield; 1093320740a0SDave May 10949566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 10959566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldSetBlockSize(gfield, blocksize)); 1096320740a0SDave May } 1097b62e03f8SDave May swarm->db->field[swarm->db->nfields - 1]->petsc_type = PETSC_DATATYPE_UNKNOWN; 10983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1099b62e03f8SDave May } 1100b62e03f8SDave May 1101d3a51819SDave May /*@C 1102d3a51819SDave May DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field 1103d3a51819SDave May 1104cc4c1da9SBarry Smith Not Collective, No Fortran Support 1105d3a51819SDave May 110660225df5SJacob Faibussowitsch Input Parameters: 110720f4b53cSBarry Smith + dm - a `DMSWARM` 110862741f57SDave May - fieldname - the textual name to identify this field 1109d3a51819SDave May 111060225df5SJacob Faibussowitsch Output Parameters: 111162741f57SDave May + blocksize - the number of each data type 1112d3a51819SDave May . type - the data type 111362741f57SDave May - data - pointer to raw array 1114d3a51819SDave May 1115d3a51819SDave May Level: beginner 1116d3a51819SDave May 1117d3a51819SDave May Notes: 111820f4b53cSBarry Smith The array must be returned using a matching call to `DMSwarmRestoreField()`. 1119d3a51819SDave May 112020f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreField()` 1121d3a51819SDave May @*/ 1122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) 1123d71ae5a4SJacob Faibussowitsch { 1124b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 112577048351SPatrick Sanan DMSwarmDataField gfield; 1126b62e03f8SDave May 1127521f74f9SMatthew G. Knepley PetscFunctionBegin; 1128ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 11299566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 11309566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 11319566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldGetAccess(gfield)); 11329566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldGetEntries(gfield, data)); 1133ad540459SPierre Jolivet if (blocksize) *blocksize = gfield->bs; 1134ad540459SPierre Jolivet if (type) *type = gfield->petsc_type; 11353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1136b62e03f8SDave May } 1137b62e03f8SDave May 1138d3a51819SDave May /*@C 1139d3a51819SDave May DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field 1140d3a51819SDave May 1141cc4c1da9SBarry Smith Not Collective, No Fortran Support 1142d3a51819SDave May 114360225df5SJacob Faibussowitsch Input Parameters: 114420f4b53cSBarry Smith + dm - a `DMSWARM` 114562741f57SDave May - fieldname - the textual name to identify this field 1146d3a51819SDave May 114760225df5SJacob Faibussowitsch Output Parameters: 114862741f57SDave May + blocksize - the number of each data type 1149d3a51819SDave May . type - the data type 115062741f57SDave May - data - pointer to raw array 1151d3a51819SDave May 1152d3a51819SDave May Level: beginner 1153d3a51819SDave May 1154d3a51819SDave May Notes: 115520f4b53cSBarry Smith The user must call `DMSwarmGetField()` prior to calling `DMSwarmRestoreField()`. 1156d3a51819SDave May 115720f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetField()` 1158d3a51819SDave May @*/ 1159d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRestoreField(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type, void **data) 1160d71ae5a4SJacob Faibussowitsch { 1161b62e03f8SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 116277048351SPatrick Sanan DMSwarmDataField gfield; 1163b62e03f8SDave May 1164521f74f9SMatthew G. Knepley PetscFunctionBegin; 1165ea7032a0SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 11669566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 11679566063dSJacob Faibussowitsch PetscCall(DMSwarmDataFieldRestoreAccess(gfield)); 1168b62e03f8SDave May if (data) *data = NULL; 11693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1170b62e03f8SDave May } 1171b62e03f8SDave May 11720bf7c1c5SMatthew G. Knepley PetscErrorCode DMSwarmGetFieldInfo(DM dm, const char fieldname[], PetscInt *blocksize, PetscDataType *type) 11730bf7c1c5SMatthew G. Knepley { 11740bf7c1c5SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)dm->data; 11750bf7c1c5SMatthew G. Knepley DMSwarmDataField gfield; 11760bf7c1c5SMatthew G. Knepley 11770bf7c1c5SMatthew G. Knepley PetscFunctionBegin; 11780bf7c1c5SMatthew G. Knepley PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMSWARM); 11790bf7c1c5SMatthew G. Knepley PetscCall(DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield)); 11800bf7c1c5SMatthew G. Knepley if (blocksize) *blocksize = gfield->bs; 11810bf7c1c5SMatthew G. Knepley if (type) *type = gfield->petsc_type; 11820bf7c1c5SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11830bf7c1c5SMatthew G. Knepley } 11840bf7c1c5SMatthew G. Knepley 118574d0cae8SMatthew G. Knepley /*@ 118620f4b53cSBarry Smith DMSwarmAddPoint - Add space for one new point in the `DMSWARM` 1187d3a51819SDave May 118820f4b53cSBarry Smith Not Collective 1189d3a51819SDave May 119060225df5SJacob Faibussowitsch Input Parameter: 119120f4b53cSBarry Smith . dm - a `DMSWARM` 1192d3a51819SDave May 1193d3a51819SDave May Level: beginner 1194d3a51819SDave May 1195d3a51819SDave May Notes: 11968b8a3813SDave May The new point will have all fields initialized to zero. 1197d3a51819SDave May 119820f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddNPoints()` 1199d3a51819SDave May @*/ 1200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddPoint(DM dm) 1201d71ae5a4SJacob Faibussowitsch { 1202cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1203cb1d1399SDave May 1204521f74f9SMatthew G. Knepley PetscFunctionBegin; 12059566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 12069566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0)); 12079566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketAddPoint(swarm->db)); 12089566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0)); 12093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1210cb1d1399SDave May } 1211cb1d1399SDave May 121274d0cae8SMatthew G. Knepley /*@ 121320f4b53cSBarry Smith DMSwarmAddNPoints - Add space for a number of new points in the `DMSWARM` 1214d3a51819SDave May 121520f4b53cSBarry Smith Not Collective 1216d3a51819SDave May 121760225df5SJacob Faibussowitsch Input Parameters: 121820f4b53cSBarry Smith + dm - a `DMSWARM` 121962741f57SDave May - npoints - the number of new points to add 1220d3a51819SDave May 1221d3a51819SDave May Level: beginner 1222d3a51819SDave May 1223d3a51819SDave May Notes: 12248b8a3813SDave May The new point will have all fields initialized to zero. 1225d3a51819SDave May 122620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmAddPoint()` 1227d3a51819SDave May @*/ 1228d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmAddNPoints(DM dm, PetscInt npoints) 1229d71ae5a4SJacob Faibussowitsch { 1230cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1231cb1d1399SDave May PetscInt nlocal; 1232cb1d1399SDave May 1233521f74f9SMatthew G. Knepley PetscFunctionBegin; 12349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_AddPoints, 0, 0, 0, 0)); 12359566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &nlocal, NULL, NULL)); 1236cb1d1399SDave May nlocal = nlocal + npoints; 12379566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketSetSizes(swarm->db, nlocal, DMSWARM_DATA_BUCKET_BUFFER_DEFAULT)); 12389566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_AddPoints, 0, 0, 0, 0)); 12393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1240cb1d1399SDave May } 1241cb1d1399SDave May 124274d0cae8SMatthew G. Knepley /*@ 124320f4b53cSBarry Smith DMSwarmRemovePoint - Remove the last point from the `DMSWARM` 1244d3a51819SDave May 124520f4b53cSBarry Smith Not Collective 1246d3a51819SDave May 124760225df5SJacob Faibussowitsch Input Parameter: 124820f4b53cSBarry Smith . dm - a `DMSWARM` 1249d3a51819SDave May 1250d3a51819SDave May Level: beginner 1251d3a51819SDave May 125220f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePointAtIndex()` 1253d3a51819SDave May @*/ 1254d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePoint(DM dm) 1255d71ae5a4SJacob Faibussowitsch { 1256cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1257cb1d1399SDave May 1258521f74f9SMatthew G. Knepley PetscFunctionBegin; 12599566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0)); 12609566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRemovePoint(swarm->db)); 12619566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0)); 12623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1263cb1d1399SDave May } 1264cb1d1399SDave May 126574d0cae8SMatthew G. Knepley /*@ 126620f4b53cSBarry Smith DMSwarmRemovePointAtIndex - Removes a specific point from the `DMSWARM` 1267d3a51819SDave May 126820f4b53cSBarry Smith Not Collective 1269d3a51819SDave May 127060225df5SJacob Faibussowitsch Input Parameters: 127120f4b53cSBarry Smith + dm - a `DMSWARM` 127262741f57SDave May - idx - index of point to remove 1273d3a51819SDave May 1274d3a51819SDave May Level: beginner 1275d3a51819SDave May 127620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()` 1277d3a51819SDave May @*/ 1278d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmRemovePointAtIndex(DM dm, PetscInt idx) 1279d71ae5a4SJacob Faibussowitsch { 1280cb1d1399SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1281cb1d1399SDave May 1282521f74f9SMatthew G. Knepley PetscFunctionBegin; 12839566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_RemovePoints, 0, 0, 0, 0)); 12849566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketRemovePointAtIndex(swarm->db, idx)); 12859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_RemovePoints, 0, 0, 0, 0)); 12863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1287cb1d1399SDave May } 1288b62e03f8SDave May 128974d0cae8SMatthew G. Knepley /*@ 129020f4b53cSBarry Smith DMSwarmCopyPoint - Copy point pj to point pi in the `DMSWARM` 1291ba4fc9c6SDave May 129220f4b53cSBarry Smith Not Collective 1293ba4fc9c6SDave May 129460225df5SJacob Faibussowitsch Input Parameters: 129520f4b53cSBarry Smith + dm - a `DMSWARM` 1296ba4fc9c6SDave May . pi - the index of the point to copy 1297ba4fc9c6SDave May - pj - the point index where the copy should be located 1298ba4fc9c6SDave May 1299ba4fc9c6SDave May Level: beginner 1300ba4fc9c6SDave May 130120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRemovePoint()` 1302ba4fc9c6SDave May @*/ 1303d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCopyPoint(DM dm, PetscInt pi, PetscInt pj) 1304d71ae5a4SJacob Faibussowitsch { 1305ba4fc9c6SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1306ba4fc9c6SDave May 1307ba4fc9c6SDave May PetscFunctionBegin; 13089566063dSJacob Faibussowitsch if (!swarm->issetup) PetscCall(DMSetUp(dm)); 13099566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCopyPoint(swarm->db, pi, swarm->db, pj)); 13103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1311ba4fc9c6SDave May } 1312ba4fc9c6SDave May 131366976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmMigrate_Basic(DM dm, PetscBool remove_sent_points) 1314d71ae5a4SJacob Faibussowitsch { 1315521f74f9SMatthew G. Knepley PetscFunctionBegin; 13169566063dSJacob Faibussowitsch PetscCall(DMSwarmMigrate_Push_Basic(dm, remove_sent_points)); 13173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13183454631fSDave May } 13193454631fSDave May 132074d0cae8SMatthew G. Knepley /*@ 132120f4b53cSBarry Smith DMSwarmMigrate - Relocates points defined in the `DMSWARM` to other MPI-ranks 1322d3a51819SDave May 132320f4b53cSBarry Smith Collective 1324d3a51819SDave May 132560225df5SJacob Faibussowitsch Input Parameters: 132620f4b53cSBarry Smith + dm - the `DMSWARM` 132762741f57SDave May - remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank 1328d3a51819SDave May 1329d3a51819SDave May Level: advanced 1330d3a51819SDave May 133120f4b53cSBarry Smith Notes: 133220f4b53cSBarry Smith The `DM` will be modified to accommodate received points. 133320f4b53cSBarry Smith If `remove_sent_points` is `PETSC_TRUE`, any points that were sent will be removed from the `DM`. 133420f4b53cSBarry Smith Different styles of migration are supported. See `DMSwarmSetMigrateType()`. 133520f4b53cSBarry Smith 133620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()` 1337d3a51819SDave May @*/ 1338d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmMigrate(DM dm, PetscBool remove_sent_points) 1339d71ae5a4SJacob Faibussowitsch { 1340f0cdbbbaSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1341f0cdbbbaSDave May 1342521f74f9SMatthew G. Knepley PetscFunctionBegin; 13439566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_Migrate, 0, 0, 0, 0)); 1344f0cdbbbaSDave May switch (swarm->migrate_type) { 1345d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_BASIC: 1346d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_Basic(dm, remove_sent_points)); 1347d71ae5a4SJacob Faibussowitsch break; 1348d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_DMCELLNSCATTER: 1349d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_CellDMScatter(dm, remove_sent_points)); 1350d71ae5a4SJacob Faibussowitsch break; 1351d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_DMCELLEXACT: 1352d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_DMCELLEXACT not implemented"); 1353d71ae5a4SJacob Faibussowitsch case DMSWARM_MIGRATE_USER: 1354d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE_USER not implemented"); 1355d71ae5a4SJacob Faibussowitsch default: 1356d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_MIGRATE type unknown"); 1357f0cdbbbaSDave May } 13589566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_Migrate, 0, 0, 0, 0)); 13599566063dSJacob Faibussowitsch PetscCall(DMClearGlobalVectors(dm)); 13603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13613454631fSDave May } 13623454631fSDave May 1363f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm, PetscInt *globalsize); 1364f0cdbbbaSDave May 1365d3a51819SDave May /* 1366d3a51819SDave May DMSwarmCollectViewCreate 1367d3a51819SDave May 1368d3a51819SDave May * Applies a collection method and gathers point neighbour points into dm 1369d3a51819SDave May 1370d3a51819SDave May Notes: 13718b8a3813SDave May Users should call DMSwarmCollectViewDestroy() after 1372d3a51819SDave May they have finished computations associated with the collected points 1373d3a51819SDave May */ 1374d3a51819SDave May 137574d0cae8SMatthew G. Knepley /*@ 1376d3a51819SDave May DMSwarmCollectViewCreate - Applies a collection method and gathers points 137720f4b53cSBarry Smith in neighbour ranks into the `DMSWARM` 1378d3a51819SDave May 137920f4b53cSBarry Smith Collective 1380d3a51819SDave May 138160225df5SJacob Faibussowitsch Input Parameter: 138220f4b53cSBarry Smith . dm - the `DMSWARM` 1383d3a51819SDave May 1384d3a51819SDave May Level: advanced 1385d3a51819SDave May 138620f4b53cSBarry Smith Notes: 138720f4b53cSBarry Smith Users should call `DMSwarmCollectViewDestroy()` after 138820f4b53cSBarry Smith they have finished computations associated with the collected points 1389*0764c050SBarry Smith 139020f4b53cSBarry Smith Different collect methods are supported. See `DMSwarmSetCollectType()`. 139120f4b53cSBarry Smith 1392*0764c050SBarry Smith Developer Note: 1393*0764c050SBarry Smith Create and Destroy routines create new objects that can get destroyed, they do not change the state 1394*0764c050SBarry Smith of the current object. 1395*0764c050SBarry Smith 139620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewDestroy()`, `DMSwarmSetCollectType()` 1397d3a51819SDave May @*/ 1398d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewCreate(DM dm) 1399d71ae5a4SJacob Faibussowitsch { 14002712d1f2SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 14012712d1f2SDave May PetscInt ng; 14022712d1f2SDave May 1403521f74f9SMatthew G. Knepley PetscFunctionBegin; 140428b400f6SJacob Faibussowitsch PetscCheck(!swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView currently active"); 14059566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &ng)); 1406480eef7bSDave May switch (swarm->collect_type) { 1407d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_BASIC: 1408d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmMigrate_GlobalToLocal_Basic(dm, &ng)); 1409d71ae5a4SJacob Faibussowitsch break; 1410d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_DMDABOUNDINGBOX: 1411d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented"); 1412d71ae5a4SJacob Faibussowitsch case DMSWARM_COLLECT_GENERAL: 1413d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT_GENERAL not implemented"); 1414d71ae5a4SJacob Faibussowitsch default: 1415d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "DMSWARM_COLLECT type unknown"); 1416480eef7bSDave May } 1417480eef7bSDave May swarm->collect_view_active = PETSC_TRUE; 1418480eef7bSDave May swarm->collect_view_reset_nlocal = ng; 14193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14202712d1f2SDave May } 14212712d1f2SDave May 142274d0cae8SMatthew G. Knepley /*@ 142320f4b53cSBarry Smith DMSwarmCollectViewDestroy - Resets the `DMSWARM` to the size prior to calling `DMSwarmCollectViewCreate()` 1424d3a51819SDave May 142520f4b53cSBarry Smith Collective 1426d3a51819SDave May 142760225df5SJacob Faibussowitsch Input Parameters: 142820f4b53cSBarry Smith . dm - the `DMSWARM` 1429d3a51819SDave May 1430d3a51819SDave May Notes: 143120f4b53cSBarry Smith Users should call `DMSwarmCollectViewCreate()` before this function is called. 1432d3a51819SDave May 1433d3a51819SDave May Level: advanced 1434d3a51819SDave May 1435*0764c050SBarry Smith Developer Note: 1436*0764c050SBarry Smith Create and Destroy routines create new objects that can get destroyed, they do not change the state 1437*0764c050SBarry Smith of the current object. 1438*0764c050SBarry Smith 143920f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmCollectViewCreate()`, `DMSwarmSetCollectType()` 1440d3a51819SDave May @*/ 1441d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmCollectViewDestroy(DM dm) 1442d71ae5a4SJacob Faibussowitsch { 14432712d1f2SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 14442712d1f2SDave May 1445521f74f9SMatthew G. Knepley PetscFunctionBegin; 144628b400f6SJacob Faibussowitsch PetscCheck(swarm->collect_view_active, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "CollectView is currently not active"); 14479566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, swarm->collect_view_reset_nlocal, -1)); 1448480eef7bSDave May swarm->collect_view_active = PETSC_FALSE; 14493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14502712d1f2SDave May } 14513454631fSDave May 145266976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmSetUpPIC(DM dm) 1453d71ae5a4SJacob Faibussowitsch { 1454f0cdbbbaSDave May PetscInt dim; 1455f0cdbbbaSDave May 1456521f74f9SMatthew G. Knepley PetscFunctionBegin; 14579566063dSJacob Faibussowitsch PetscCall(DMSwarmSetNumSpecies(dm, 1)); 14589566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 145963a3b9bcSJacob Faibussowitsch PetscCheck(dim >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim); 146063a3b9bcSJacob Faibussowitsch PetscCheck(dim <= 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Dimension must be 1,2,3 - found %" PetscInt_FMT, dim); 14619566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_coor, dim, PETSC_DOUBLE)); 14629566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(dm, DMSwarmPICField_cellid, 1, PETSC_INT)); 14633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1464f0cdbbbaSDave May } 1465f0cdbbbaSDave May 146674d0cae8SMatthew G. Knepley /*@ 146731403186SMatthew G. Knepley DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell 146831403186SMatthew G. Knepley 146920f4b53cSBarry Smith Collective 147031403186SMatthew G. Knepley 147160225df5SJacob Faibussowitsch Input Parameters: 147220f4b53cSBarry Smith + dm - the `DMSWARM` 147320f4b53cSBarry Smith - Npc - The number of particles per cell in the cell `DM` 147431403186SMatthew G. Knepley 147531403186SMatthew G. Knepley Level: intermediate 147631403186SMatthew G. Knepley 147720f4b53cSBarry Smith Notes: 147820f4b53cSBarry Smith The user must use `DMSwarmSetCellDM()` to set the cell `DM` first. The particles are placed randomly inside each cell. If only 147920f4b53cSBarry Smith one particle is in each cell, it is placed at the centroid. 148020f4b53cSBarry Smith 148120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetCellDM()` 148231403186SMatthew G. Knepley @*/ 1483d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc) 1484d71ae5a4SJacob Faibussowitsch { 148531403186SMatthew G. Knepley DM cdm; 148631403186SMatthew G. Knepley PetscRandom rnd; 148731403186SMatthew G. Knepley DMPolytopeType ct; 148831403186SMatthew G. Knepley PetscBool simplex; 148931403186SMatthew G. Knepley PetscReal *centroid, *coords, *xi0, *v0, *J, *invJ, detJ; 149031403186SMatthew G. Knepley PetscInt dim, d, cStart, cEnd, c, p; 149131403186SMatthew G. Knepley 149231403186SMatthew G. Knepley PetscFunctionBeginUser; 14939566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd)); 14949566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0)); 14959566063dSJacob Faibussowitsch PetscCall(PetscRandomSetType(rnd, PETSCRAND48)); 149631403186SMatthew G. Knepley 14979566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &cdm)); 14989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(cdm, &dim)); 14999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd)); 15009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(cdm, cStart, &ct)); 150131403186SMatthew G. Knepley simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE; 150231403186SMatthew G. Knepley 15039566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(dim, ¢roid, dim, &xi0, dim, &v0, dim * dim, &J, dim * dim, &invJ)); 150431403186SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 15059566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 150631403186SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 150731403186SMatthew G. Knepley if (Npc == 1) { 15089566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL)); 150931403186SMatthew G. Knepley for (d = 0; d < dim; ++d) coords[c * dim + d] = centroid[d]; 151031403186SMatthew G. Knepley } else { 15119566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ)); /* affine */ 151231403186SMatthew G. Knepley for (p = 0; p < Npc; ++p) { 151331403186SMatthew G. Knepley const PetscInt n = c * Npc + p; 151431403186SMatthew G. Knepley PetscReal sum = 0.0, refcoords[3]; 151531403186SMatthew G. Knepley 151631403186SMatthew G. Knepley for (d = 0; d < dim; ++d) { 15179566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValueReal(rnd, &refcoords[d])); 151831403186SMatthew G. Knepley sum += refcoords[d]; 151931403186SMatthew G. Knepley } 15209371c9d4SSatish Balay if (simplex && sum > 0.0) 15219371c9d4SSatish Balay for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim) * sum; 152231403186SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n * dim]); 152331403186SMatthew G. Knepley } 152431403186SMatthew G. Knepley } 152531403186SMatthew G. Knepley } 15269566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&coords)); 15279566063dSJacob Faibussowitsch PetscCall(PetscFree5(centroid, xi0, v0, J, invJ)); 15289566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rnd)); 15293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 153031403186SMatthew G. Knepley } 153131403186SMatthew G. Knepley 153231403186SMatthew G. Knepley /*@ 153320f4b53cSBarry Smith DMSwarmSetType - Set particular flavor of `DMSWARM` 1534d3a51819SDave May 153520f4b53cSBarry Smith Collective 1536d3a51819SDave May 153760225df5SJacob Faibussowitsch Input Parameters: 153820f4b53cSBarry Smith + dm - the `DMSWARM` 153920f4b53cSBarry Smith - stype - the `DMSWARM` type (e.g. `DMSWARM_PIC`) 1540d3a51819SDave May 1541d3a51819SDave May Level: advanced 1542d3a51819SDave May 154320f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetMigrateType()`, `DMSwarmSetCollectType()`, `DMSwarmType`, `DMSWARM_PIC`, `DMSWARM_BASIC` 1544d3a51819SDave May @*/ 1545d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetType(DM dm, DMSwarmType stype) 1546d71ae5a4SJacob Faibussowitsch { 1547f0cdbbbaSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 1548f0cdbbbaSDave May 1549521f74f9SMatthew G. Knepley PetscFunctionBegin; 1550f0cdbbbaSDave May swarm->swarm_type = stype; 155148a46eb9SPierre Jolivet if (swarm->swarm_type == DMSWARM_PIC) PetscCall(DMSwarmSetUpPIC(dm)); 15523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1553f0cdbbbaSDave May } 1554f0cdbbbaSDave May 155566976f2fSJacob Faibussowitsch static PetscErrorCode DMSetup_Swarm(DM dm) 1556d71ae5a4SJacob Faibussowitsch { 15573454631fSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 15583454631fSDave May PetscMPIInt rank; 15593454631fSDave May PetscInt p, npoints, *rankval; 15603454631fSDave May 1561521f74f9SMatthew G. Knepley PetscFunctionBegin; 15623ba16761SJacob Faibussowitsch if (swarm->issetup) PetscFunctionReturn(PETSC_SUCCESS); 15633454631fSDave May swarm->issetup = PETSC_TRUE; 15643454631fSDave May 1565f0cdbbbaSDave May if (swarm->swarm_type == DMSWARM_PIC) { 1566f0cdbbbaSDave May /* check dmcell exists */ 156728b400f6SJacob Faibussowitsch PetscCheck(swarm->dmcell, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires you call DMSwarmSetCellDM"); 1568f0cdbbbaSDave May 1569f0cdbbbaSDave May if (swarm->dmcell->ops->locatepointssubdomain) { 1570f0cdbbbaSDave May /* check methods exists for exact ownership identificiation */ 15719566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n")); 1572f0cdbbbaSDave May swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT; 1573f0cdbbbaSDave May } else { 1574f0cdbbbaSDave May /* check methods exist for point location AND rank neighbor identification */ 1575f0cdbbbaSDave May if (swarm->dmcell->ops->locatepoints) { 15769566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n")); 1577f0cdbbbaSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined"); 1578f0cdbbbaSDave May 1579f0cdbbbaSDave May if (swarm->dmcell->ops->getneighbors) { 15809566063dSJacob Faibussowitsch PetscCall(PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n")); 1581f0cdbbbaSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined"); 1582f0cdbbbaSDave May 1583f0cdbbbaSDave May swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER; 1584f0cdbbbaSDave May } 1585f0cdbbbaSDave May } 1586f0cdbbbaSDave May 15879566063dSJacob Faibussowitsch PetscCall(DMSwarmFinalizeFieldRegister(dm)); 1588f0cdbbbaSDave May 15893454631fSDave May /* check some fields were registered */ 159008401ef6SPierre Jolivet PetscCheck(swarm->db->nfields > 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "At least one field user must be registered via DMSwarmRegisterXXX()"); 15913454631fSDave May 15923454631fSDave May /* check local sizes were set */ 159308401ef6SPierre Jolivet PetscCheck(swarm->db->L != -1, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Local sizes must be set via DMSwarmSetLocalSizes()"); 15943454631fSDave May 15953454631fSDave May /* initialize values in pid and rank placeholders */ 15963454631fSDave May /* TODO: [pid - use MPI_Scan] */ 15979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15989566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketGetSizes(swarm->db, &npoints, NULL, NULL)); 15999566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval)); 1600ad540459SPierre Jolivet for (p = 0; p < npoints; p++) rankval[p] = (PetscInt)rank; 16019566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmField_rank, NULL, NULL, (void **)&rankval)); 16023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16033454631fSDave May } 16043454631fSDave May 1605dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx); 1606dc5f5ce9SDave May 160766976f2fSJacob Faibussowitsch static PetscErrorCode DMDestroy_Swarm(DM dm) 1608d71ae5a4SJacob Faibussowitsch { 160957795646SDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 161057795646SDave May 161157795646SDave May PetscFunctionBegin; 16123ba16761SJacob Faibussowitsch if (--swarm->refct > 0) PetscFunctionReturn(PETSC_SUCCESS); 16139566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketDestroy(&swarm->db)); 161448a46eb9SPierre Jolivet if (swarm->sort_context) PetscCall(DMSwarmSortDestroy(&swarm->sort_context)); 16159566063dSJacob Faibussowitsch PetscCall(PetscFree(swarm)); 16163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 161757795646SDave May } 161857795646SDave May 161966976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer) 1620d71ae5a4SJacob Faibussowitsch { 1621a9ee3421SMatthew G. Knepley DM cdm; 1622a9ee3421SMatthew G. Knepley PetscDraw draw; 162331403186SMatthew G. Knepley PetscReal *coords, oldPause, radius = 0.01; 1624a9ee3421SMatthew G. Knepley PetscInt Np, p, bs; 1625a9ee3421SMatthew G. Knepley 1626a9ee3421SMatthew G. Knepley PetscFunctionBegin; 16279566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, ((PetscObject)dm)->prefix, "-dm_view_swarm_radius", &radius, NULL)); 16289566063dSJacob Faibussowitsch PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw)); 16299566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &cdm)); 16309566063dSJacob Faibussowitsch PetscCall(PetscDrawGetPause(draw, &oldPause)); 16319566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, 0.0)); 16329566063dSJacob Faibussowitsch PetscCall(DMView(cdm, viewer)); 16339566063dSJacob Faibussowitsch PetscCall(PetscDrawSetPause(draw, oldPause)); 1634a9ee3421SMatthew G. Knepley 16359566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &Np)); 16369566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **)&coords)); 1637a9ee3421SMatthew G. Knepley for (p = 0; p < Np; ++p) { 1638a9ee3421SMatthew G. Knepley const PetscInt i = p * bs; 1639a9ee3421SMatthew G. Knepley 16409566063dSJacob Faibussowitsch PetscCall(PetscDrawEllipse(draw, coords[i], coords[i + 1], radius, radius, PETSC_DRAW_BLUE)); 1641a9ee3421SMatthew G. Knepley } 16429566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **)&coords)); 16439566063dSJacob Faibussowitsch PetscCall(PetscDrawFlush(draw)); 16449566063dSJacob Faibussowitsch PetscCall(PetscDrawPause(draw)); 16459566063dSJacob Faibussowitsch PetscCall(PetscDrawSave(draw)); 16463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1647a9ee3421SMatthew G. Knepley } 1648a9ee3421SMatthew G. Knepley 1649d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMView_Swarm_Ascii(DM dm, PetscViewer viewer) 1650d71ae5a4SJacob Faibussowitsch { 16516a5217c0SMatthew G. Knepley PetscViewerFormat format; 16526a5217c0SMatthew G. Knepley PetscInt *sizes; 16536a5217c0SMatthew G. Knepley PetscInt dim, Np, maxSize = 17; 16546a5217c0SMatthew G. Knepley MPI_Comm comm; 16556a5217c0SMatthew G. Knepley PetscMPIInt rank, size, p; 16566a5217c0SMatthew G. Knepley const char *name; 16576a5217c0SMatthew G. Knepley 16586a5217c0SMatthew G. Knepley PetscFunctionBegin; 16596a5217c0SMatthew G. Knepley PetscCall(PetscViewerGetFormat(viewer, &format)); 16606a5217c0SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 16616a5217c0SMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(dm, &Np)); 16626a5217c0SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 16636a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 16646a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(comm, &size)); 16656a5217c0SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 166663a3b9bcSJacob Faibussowitsch if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s")); 166763a3b9bcSJacob Faibussowitsch else PetscCall(PetscViewerASCIIPrintf(viewer, "Swarm in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s")); 16686a5217c0SMatthew G. Knepley if (size < maxSize) PetscCall(PetscCalloc1(size, &sizes)); 16696a5217c0SMatthew G. Knepley else PetscCall(PetscCalloc1(3, &sizes)); 16706a5217c0SMatthew G. Knepley if (size < maxSize) { 16716a5217c0SMatthew G. Knepley PetscCallMPI(MPI_Gather(&Np, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm)); 16726a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Number of particles per rank:")); 16736a5217c0SMatthew G. Knepley for (p = 0; p < size; ++p) { 16746a5217c0SMatthew G. Knepley if (rank == 0) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p])); 16756a5217c0SMatthew G. Knepley } 16766a5217c0SMatthew G. Knepley } else { 16776a5217c0SMatthew G. Knepley PetscInt locMinMax[2] = {Np, Np}; 16786a5217c0SMatthew G. Knepley 16796a5217c0SMatthew G. Knepley PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes)); 16806a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Min/Max of particles per rank: %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1])); 16816a5217c0SMatthew G. Knepley } 16826a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 16836a5217c0SMatthew G. Knepley PetscCall(PetscFree(sizes)); 16846a5217c0SMatthew G. Knepley if (format == PETSC_VIEWER_ASCII_INFO) { 16856a5217c0SMatthew G. Knepley PetscInt *cell; 16866a5217c0SMatthew G. Knepley 16876a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, " Cells containing each particle:\n")); 16886a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 16896a5217c0SMatthew G. Knepley PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell)); 169063a3b9bcSJacob Faibussowitsch for (p = 0; p < Np; ++p) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " p%d: %" PetscInt_FMT "\n", p, cell[p])); 16916a5217c0SMatthew G. Knepley PetscCall(PetscViewerFlush(viewer)); 16926a5217c0SMatthew G. Knepley PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 16936a5217c0SMatthew G. Knepley PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&cell)); 16946a5217c0SMatthew G. Knepley } 16953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16966a5217c0SMatthew G. Knepley } 16976a5217c0SMatthew G. Knepley 169866976f2fSJacob Faibussowitsch static PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer) 1699d71ae5a4SJacob Faibussowitsch { 17005f50eb2eSDave May DM_Swarm *swarm = (DM_Swarm *)dm->data; 17015627991aSBarry Smith PetscBool iascii, ibinary, isvtk, isdraw; 17025627991aSBarry Smith #if defined(PETSC_HAVE_HDF5) 17035627991aSBarry Smith PetscBool ishdf5; 17045627991aSBarry Smith #endif 17055f50eb2eSDave May 17065f50eb2eSDave May PetscFunctionBegin; 17075f50eb2eSDave May PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17085f50eb2eSDave May PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 17099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 17109566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &ibinary)); 17119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk)); 17125627991aSBarry Smith #if defined(PETSC_HAVE_HDF5) 17139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5)); 17145627991aSBarry Smith #endif 17159566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 17165f50eb2eSDave May if (iascii) { 17176a5217c0SMatthew G. Knepley PetscViewerFormat format; 17186a5217c0SMatthew G. Knepley 17196a5217c0SMatthew G. Knepley PetscCall(PetscViewerGetFormat(viewer, &format)); 17206a5217c0SMatthew G. Knepley switch (format) { 1721d71ae5a4SJacob Faibussowitsch case PETSC_VIEWER_ASCII_INFO_DETAIL: 1722d71ae5a4SJacob Faibussowitsch PetscCall(DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm), swarm->db, NULL, DATABUCKET_VIEW_STDOUT)); 1723d71ae5a4SJacob Faibussowitsch break; 1724d71ae5a4SJacob Faibussowitsch default: 1725d71ae5a4SJacob Faibussowitsch PetscCall(DMView_Swarm_Ascii(dm, viewer)); 17266a5217c0SMatthew G. Knepley } 1727f7d195e4SLawrence Mitchell } else { 17285f50eb2eSDave May #if defined(PETSC_HAVE_HDF5) 172948a46eb9SPierre Jolivet if (ishdf5) PetscCall(DMSwarmView_HDF5(dm, viewer)); 17305f50eb2eSDave May #endif 173148a46eb9SPierre Jolivet if (isdraw) PetscCall(DMSwarmView_Draw(dm, viewer)); 1732f7d195e4SLawrence Mitchell } 17333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17345f50eb2eSDave May } 17355f50eb2eSDave May 1736cc4c1da9SBarry Smith /*@ 173720f4b53cSBarry Smith DMSwarmGetCellSwarm - Extracts a single cell from the `DMSWARM` object, returns it as a single cell `DMSWARM`. 173820f4b53cSBarry 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. 1739d0c080abSJoseph Pusztay 1740d0c080abSJoseph Pusztay Noncollective 1741d0c080abSJoseph Pusztay 174260225df5SJacob Faibussowitsch Input Parameters: 174320f4b53cSBarry Smith + sw - the `DMSWARM` 17445627991aSBarry Smith . cellID - the integer id of the cell to be extracted and filtered 174520f4b53cSBarry Smith - cellswarm - The `DMSWARM` to receive the cell 1746d0c080abSJoseph Pusztay 1747d0c080abSJoseph Pusztay Level: beginner 1748d0c080abSJoseph Pusztay 17495627991aSBarry Smith Notes: 175020f4b53cSBarry Smith This presently only supports `DMSWARM_PIC` type 17515627991aSBarry Smith 175220f4b53cSBarry Smith Should be restored with `DMSwarmRestoreCellSwarm()` 1753d0c080abSJoseph Pusztay 175420f4b53cSBarry Smith Changes to this cell of the swarm will be lost if they are made prior to restoring this cell. 175520f4b53cSBarry Smith 175620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmRestoreCellSwarm()` 1757d0c080abSJoseph Pusztay @*/ 1758cc4c1da9SBarry Smith PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm) 1759d71ae5a4SJacob Faibussowitsch { 1760d0c080abSJoseph Pusztay DM_Swarm *original = (DM_Swarm *)sw->data; 1761d0c080abSJoseph Pusztay DMLabel label; 1762d0c080abSJoseph Pusztay DM dmc, subdmc; 1763d0c080abSJoseph Pusztay PetscInt *pids, particles, dim; 1764d0c080abSJoseph Pusztay 1765d0c080abSJoseph Pusztay PetscFunctionBegin; 1766d0c080abSJoseph Pusztay /* Configure new swarm */ 17679566063dSJacob Faibussowitsch PetscCall(DMSetType(cellswarm, DMSWARM)); 17689566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 17699566063dSJacob Faibussowitsch PetscCall(DMSetDimension(cellswarm, dim)); 17709566063dSJacob Faibussowitsch PetscCall(DMSwarmSetType(cellswarm, DMSWARM_PIC)); 1771d0c080abSJoseph Pusztay /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */ 17729566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketDestroy(&((DM_Swarm *)cellswarm->data)->db)); 17739566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 17749566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles)); 17759566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids)); 17769566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm *)cellswarm->data)->db)); 17779566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 17789566063dSJacob Faibussowitsch PetscCall(PetscFree(pids)); 17799566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(sw, &dmc)); 17809566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label)); 17819566063dSJacob Faibussowitsch PetscCall(DMAddLabel(dmc, label)); 17829566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, cellID, 1)); 178330cbcd5dSksagiyam PetscCall(DMPlexFilter(dmc, label, 1, PETSC_FALSE, PETSC_FALSE, NULL, &subdmc)); 17849566063dSJacob Faibussowitsch PetscCall(DMSwarmSetCellDM(cellswarm, subdmc)); 17859566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&label)); 17863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1787d0c080abSJoseph Pusztay } 1788d0c080abSJoseph Pusztay 1789cc4c1da9SBarry Smith /*@ 179020f4b53cSBarry Smith DMSwarmRestoreCellSwarm - Restores a `DMSWARM` object obtained with `DMSwarmGetCellSwarm()`. All fields are copied back into the parent swarm. 1791d0c080abSJoseph Pusztay 1792d0c080abSJoseph Pusztay Noncollective 1793d0c080abSJoseph Pusztay 179460225df5SJacob Faibussowitsch Input Parameters: 179520f4b53cSBarry Smith + sw - the parent `DMSWARM` 1796d0c080abSJoseph Pusztay . cellID - the integer id of the cell to be copied back into the parent swarm 1797d0c080abSJoseph Pusztay - cellswarm - the cell swarm object 1798d0c080abSJoseph Pusztay 1799d0c080abSJoseph Pusztay Level: beginner 1800d0c080abSJoseph Pusztay 18015627991aSBarry Smith Note: 180220f4b53cSBarry Smith This only supports `DMSWARM_PIC` types of `DMSWARM`s 1803d0c080abSJoseph Pusztay 180420f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmGetCellSwarm()` 1805d0c080abSJoseph Pusztay @*/ 1806cc4c1da9SBarry Smith PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm) 1807d71ae5a4SJacob Faibussowitsch { 1808d0c080abSJoseph Pusztay DM dmc; 1809d0c080abSJoseph Pusztay PetscInt *pids, particles, p; 1810d0c080abSJoseph Pusztay 1811d0c080abSJoseph Pusztay PetscFunctionBegin; 18129566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 18139566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids)); 18149566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 1815d0c080abSJoseph Pusztay /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */ 181648a46eb9SPierre Jolivet for (p = 0; p < particles; ++p) PetscCall(DMSwarmDataBucketCopyPoint(((DM_Swarm *)cellswarm->data)->db, pids[p], ((DM_Swarm *)sw->data)->db, pids[p])); 1817d0c080abSJoseph Pusztay /* Free memory, destroy cell dm */ 18189566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(cellswarm, &dmc)); 18199566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dmc)); 18209566063dSJacob Faibussowitsch PetscCall(PetscFree(pids)); 18213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1822d0c080abSJoseph Pusztay } 1823d0c080abSJoseph Pusztay 1824d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *); 1825d0c080abSJoseph Pusztay 1826d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Swarm(DM sw) 1827d71ae5a4SJacob Faibussowitsch { 1828d0c080abSJoseph Pusztay PetscFunctionBegin; 1829d0c080abSJoseph Pusztay sw->dim = 0; 1830d0c080abSJoseph Pusztay sw->ops->view = DMView_Swarm; 1831d0c080abSJoseph Pusztay sw->ops->load = NULL; 1832d0c080abSJoseph Pusztay sw->ops->setfromoptions = NULL; 1833d0c080abSJoseph Pusztay sw->ops->clone = DMClone_Swarm; 1834d0c080abSJoseph Pusztay sw->ops->setup = DMSetup_Swarm; 1835d0c080abSJoseph Pusztay sw->ops->createlocalsection = NULL; 1836adc21957SMatthew G. Knepley sw->ops->createsectionpermutation = NULL; 1837d0c080abSJoseph Pusztay sw->ops->createdefaultconstraints = NULL; 1838d0c080abSJoseph Pusztay sw->ops->createglobalvector = DMCreateGlobalVector_Swarm; 1839d0c080abSJoseph Pusztay sw->ops->createlocalvector = DMCreateLocalVector_Swarm; 1840d0c080abSJoseph Pusztay sw->ops->getlocaltoglobalmapping = NULL; 1841d0c080abSJoseph Pusztay sw->ops->createfieldis = NULL; 1842d0c080abSJoseph Pusztay sw->ops->createcoordinatedm = NULL; 1843d0c080abSJoseph Pusztay sw->ops->getcoloring = NULL; 1844d0c080abSJoseph Pusztay sw->ops->creatematrix = DMCreateMatrix_Swarm; 1845d0c080abSJoseph Pusztay sw->ops->createinterpolation = NULL; 1846d0c080abSJoseph Pusztay sw->ops->createinjection = NULL; 1847d0c080abSJoseph Pusztay sw->ops->createmassmatrix = DMCreateMassMatrix_Swarm; 1848d0c080abSJoseph Pusztay sw->ops->refine = NULL; 1849d0c080abSJoseph Pusztay sw->ops->coarsen = NULL; 1850d0c080abSJoseph Pusztay sw->ops->refinehierarchy = NULL; 1851d0c080abSJoseph Pusztay sw->ops->coarsenhierarchy = NULL; 1852d0c080abSJoseph Pusztay sw->ops->globaltolocalbegin = NULL; 1853d0c080abSJoseph Pusztay sw->ops->globaltolocalend = NULL; 1854d0c080abSJoseph Pusztay sw->ops->localtoglobalbegin = NULL; 1855d0c080abSJoseph Pusztay sw->ops->localtoglobalend = NULL; 1856d0c080abSJoseph Pusztay sw->ops->destroy = DMDestroy_Swarm; 1857d0c080abSJoseph Pusztay sw->ops->createsubdm = NULL; 1858d0c080abSJoseph Pusztay sw->ops->getdimpoints = NULL; 1859d0c080abSJoseph Pusztay sw->ops->locatepoints = NULL; 18603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1861d0c080abSJoseph Pusztay } 1862d0c080abSJoseph Pusztay 1863d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm) 1864d71ae5a4SJacob Faibussowitsch { 1865d0c080abSJoseph Pusztay DM_Swarm *swarm = (DM_Swarm *)dm->data; 1866d0c080abSJoseph Pusztay 1867d0c080abSJoseph Pusztay PetscFunctionBegin; 1868d0c080abSJoseph Pusztay swarm->refct++; 1869d0c080abSJoseph Pusztay (*newdm)->data = swarm; 18709566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMSWARM)); 18719566063dSJacob Faibussowitsch PetscCall(DMInitialize_Swarm(*newdm)); 18722e56dffeSJoe Pusztay (*newdm)->dim = dm->dim; 18733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1874d0c080abSJoseph Pusztay } 1875d0c080abSJoseph Pusztay 1876d3a51819SDave May /*MC 187720f4b53cSBarry Smith DMSWARM = "swarm" - A `DM` object used to represent arrays of data (fields) of arbitrary data type. 187862741f57SDave May This implementation was designed for particle methods in which the underlying 1879d3a51819SDave May data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type. 1880d3a51819SDave May 188120f4b53cSBarry Smith Level: intermediate 188220f4b53cSBarry Smith 188320f4b53cSBarry Smith Notes: 188420f4b53cSBarry Smith User data can be represented by `DMSWARM` through a registering "fields". 188562741f57SDave May To register a field, the user must provide; 188662741f57SDave May (a) a unique name; 188762741f57SDave May (b) the data type (or size in bytes); 188862741f57SDave May (c) the block size of the data. 1889d3a51819SDave May 1890d3a51819SDave May For example, suppose the application requires a unique id, energy, momentum and density to be stored 1891c215a47eSMatthew Knepley on a set of particles. Then the following code could be used 189220f4b53cSBarry Smith .vb 189320f4b53cSBarry Smith DMSwarmInitializeFieldRegister(dm) 189420f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG); 189520f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL); 189620f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL); 189720f4b53cSBarry Smith DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT); 189820f4b53cSBarry Smith DMSwarmFinalizeFieldRegister(dm) 189920f4b53cSBarry Smith .ve 1900d3a51819SDave May 190120f4b53cSBarry Smith The fields represented by `DMSWARM` are dynamic and can be re-sized at any time. 190220f4b53cSBarry Smith The only restriction imposed by `DMSWARM` is that all fields contain the same number of points. 1903d3a51819SDave May 1904d3a51819SDave May To support particle methods, "migration" techniques are provided. These methods migrate data 19055627991aSBarry Smith between ranks. 1906d3a51819SDave May 190720f4b53cSBarry Smith `DMSWARM` supports the methods `DMCreateGlobalVector()` and `DMCreateLocalVector()`. 190820f4b53cSBarry Smith As a `DMSWARM` may internally define and store values of different data types, 190920f4b53cSBarry Smith before calling `DMCreateGlobalVector()` or `DMCreateLocalVector()`, the user must inform `DMSWARM` which 191020f4b53cSBarry Smith fields should be used to define a `Vec` object via 191120f4b53cSBarry Smith `DMSwarmVectorDefineField()` 1912c215a47eSMatthew Knepley The specified field can be changed at any time - thereby permitting vectors 1913c215a47eSMatthew Knepley compatible with different fields to be created. 1914d3a51819SDave May 191520f4b53cSBarry Smith A dual representation of fields in the `DMSWARM` and a Vec object is permitted via 191620f4b53cSBarry Smith `DMSwarmCreateGlobalVectorFromField()` 191720f4b53cSBarry Smith Here the data defining the field in the `DMSWARM` is shared with a Vec. 1918d3a51819SDave May This is inherently unsafe if you alter the size of the field at any time between 191920f4b53cSBarry Smith calls to `DMSwarmCreateGlobalVectorFromField()` and `DMSwarmDestroyGlobalVectorFromField()`. 192020f4b53cSBarry Smith If the local size of the `DMSWARM` does not match the local size of the global vector 192120f4b53cSBarry Smith when `DMSwarmDestroyGlobalVectorFromField()` is called, an error is thrown. 1922d3a51819SDave May 192362741f57SDave May Additional high-level support is provided for Particle-In-Cell methods. 192420f4b53cSBarry Smith Please refer to `DMSwarmSetType()`. 192562741f57SDave May 192620f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMType`, `DMCreate()`, `DMSetType()` 1927d3a51819SDave May M*/ 1928cc4c1da9SBarry Smith 1929d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm) 1930d71ae5a4SJacob Faibussowitsch { 193157795646SDave May DM_Swarm *swarm; 193257795646SDave May 193357795646SDave May PetscFunctionBegin; 193457795646SDave May PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19354dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&swarm)); 1936f0cdbbbaSDave May dm->data = swarm; 19379566063dSJacob Faibussowitsch PetscCall(DMSwarmDataBucketCreate(&swarm->db)); 19389566063dSJacob Faibussowitsch PetscCall(DMSwarmInitializeFieldRegister(dm)); 1939d0c080abSJoseph Pusztay swarm->refct = 1; 1940b5bcf523SDave May swarm->vec_field_set = PETSC_FALSE; 19413454631fSDave May swarm->issetup = PETSC_FALSE; 1942480eef7bSDave May swarm->swarm_type = DMSWARM_BASIC; 1943480eef7bSDave May swarm->migrate_type = DMSWARM_MIGRATE_BASIC; 1944480eef7bSDave May swarm->collect_type = DMSWARM_COLLECT_BASIC; 194540c453e9SDave May swarm->migrate_error_on_missing_point = PETSC_FALSE; 1946f0cdbbbaSDave May swarm->dmcell = NULL; 1947f0cdbbbaSDave May swarm->collect_view_active = PETSC_FALSE; 1948f0cdbbbaSDave May swarm->collect_view_reset_nlocal = -1; 19499566063dSJacob Faibussowitsch PetscCall(DMInitialize_Swarm(dm)); 19502e956fe4SStefano Zampini if (SwarmDataFieldId == -1) PetscCall(PetscObjectComposedDataRegister(&SwarmDataFieldId)); 19513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 195257795646SDave May } 1953