10e2ec84fSDave May #define PETSCDM_DLL 20e2ec84fSDave May #include <petsc/private/dmswarmimpl.h> /*I "petscdmswarm.h" I*/ 30e2ec84fSDave May #include <petscsf.h> 4b799feefSDave May #include <petscdmda.h> 5b799feefSDave May #include <petscdmplex.h> 635b38c60SMatthew G. Knepley #include <petscdt.h> 7279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h" 80e2ec84fSDave May 935b38c60SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> /* For CoordinatesRefToReal() */ 1035b38c60SMatthew G. Knepley 110e2ec84fSDave May /* Coordinate insertition/addition API */ 12cc4c1da9SBarry Smith /*@ 1320f4b53cSBarry Smith DMSwarmSetPointsUniformCoordinates - Set point coordinates in a `DMSWARM` on a regular (ijk) grid 140e2ec84fSDave May 1520f4b53cSBarry Smith Collective 160e2ec84fSDave May 1760225df5SJacob Faibussowitsch Input Parameters: 1820f4b53cSBarry Smith + dm - the `DMSWARM` 190e2ec84fSDave May . min - minimum coordinate values in the x, y, z directions (array of length dim) 200e2ec84fSDave May . max - maximum coordinate values in the x, y, z directions (array of length dim) 210e2ec84fSDave May . npoints - number of points in each spatial direction (array of length dim) 2220f4b53cSBarry Smith - mode - indicates whether to append points to the swarm (`ADD_VALUES`), or over-ride existing points (`INSERT_VALUES`) 230e2ec84fSDave May 240e2ec84fSDave May Level: beginner 250e2ec84fSDave May 260e2ec84fSDave May Notes: 2720f4b53cSBarry Smith When using mode = `INSERT_VALUES`, this method will reset the number of particles in the `DMSWARM` 28a3b724e8SBarry Smith to be `npoints[0]` x `npoints[1]` (2D) or `npoints[0]` x `npoints[1]` x `npoints[2]` (3D). When using mode = `ADD_VALUES`, 2920f4b53cSBarry Smith new points will be appended to any already existing in the `DMSWARM` 300e2ec84fSDave May 3120f4b53cSBarry Smith .seealso: `DM`, `DMSWARM`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType` 320e2ec84fSDave May @*/ 33cc4c1da9SBarry Smith PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm, PetscReal min[], PetscReal max[], PetscInt npoints[], InsertMode mode) 34d71ae5a4SJacob Faibussowitsch { 35c448b993SMatthew G. Knepley PetscReal lmin[] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 36c448b993SMatthew G. Knepley PetscReal lmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 37c448b993SMatthew G. Knepley PetscInt i, j, k, bs, b, n_estimate, n_curr, n_new_est, p, n_found; 380e2ec84fSDave May const PetscScalar *_coor; 390e2ec84fSDave May DM celldm; 400e2ec84fSDave May PetscReal dx[3]; 412e3d3761SDave May PetscInt _npoints[] = {0, 0, 1}; 420e2ec84fSDave May Vec pos; 430e2ec84fSDave May PetscScalar *_pos; 440e2ec84fSDave May PetscReal *swarm_coor; 450e2ec84fSDave May PetscInt *swarm_cellid; 460e2ec84fSDave May PetscSF sfcell = NULL; 470e2ec84fSDave May const PetscSFNode *LA_sfcell; 480e2ec84fSDave May 490e2ec84fSDave May PetscFunctionBegin; 500e2ec84fSDave May DMSWARMPICVALID(dm); 519566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 52c448b993SMatthew G. Knepley PetscCall(DMGetLocalBoundingBox(celldm, lmin, lmax)); 53c448b993SMatthew G. Knepley PetscCall(DMGetCoordinateDim(celldm, &bs)); 540e2ec84fSDave May 550e2ec84fSDave May for (b = 0; b < bs; b++) { 5671844bb8SDave May if (npoints[b] > 1) { 570e2ec84fSDave May dx[b] = (max[b] - min[b]) / ((PetscReal)(npoints[b] - 1)); 5871844bb8SDave May } else { 5971844bb8SDave May dx[b] = 0.0; 6071844bb8SDave May } 612e3d3761SDave May _npoints[b] = npoints[b]; 620e2ec84fSDave May } 630e2ec84fSDave May 640e2ec84fSDave May /* determine number of points living in the bounding box */ 650e2ec84fSDave May n_estimate = 0; 662e3d3761SDave May for (k = 0; k < _npoints[2]; k++) { 672e3d3761SDave May for (j = 0; j < _npoints[1]; j++) { 682e3d3761SDave May for (i = 0; i < _npoints[0]; i++) { 690e2ec84fSDave May PetscReal xp[] = {0.0, 0.0, 0.0}; 700e2ec84fSDave May PetscInt ijk[3]; 710e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 720e2ec84fSDave May 730e2ec84fSDave May ijk[0] = i; 740e2ec84fSDave May ijk[1] = j; 750e2ec84fSDave May ijk[2] = k; 76ad540459SPierre Jolivet for (b = 0; b < bs; b++) xp[b] = min[b] + ijk[b] * dx[b]; 770e2ec84fSDave May for (b = 0; b < bs; b++) { 78c448b993SMatthew G. Knepley if (xp[b] < lmin[b]) point_inside = PETSC_FALSE; 79c448b993SMatthew G. Knepley if (xp[b] > lmax[b]) point_inside = PETSC_FALSE; 800e2ec84fSDave May } 81ad540459SPierre Jolivet if (point_inside) n_estimate++; 820e2ec84fSDave May } 830e2ec84fSDave May } 840e2ec84fSDave May } 850e2ec84fSDave May 860e2ec84fSDave May /* create candidate list */ 879566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &pos)); 889566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pos, bs * n_estimate, PETSC_DECIDE)); 899566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(pos, bs)); 909566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pos)); 919566063dSJacob Faibussowitsch PetscCall(VecGetArray(pos, &_pos)); 920e2ec84fSDave May 930e2ec84fSDave May n_estimate = 0; 942e3d3761SDave May for (k = 0; k < _npoints[2]; k++) { 952e3d3761SDave May for (j = 0; j < _npoints[1]; j++) { 962e3d3761SDave May for (i = 0; i < _npoints[0]; i++) { 970e2ec84fSDave May PetscReal xp[] = {0.0, 0.0, 0.0}; 980e2ec84fSDave May PetscInt ijk[3]; 990e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 1000e2ec84fSDave May 1010e2ec84fSDave May ijk[0] = i; 1020e2ec84fSDave May ijk[1] = j; 1030e2ec84fSDave May ijk[2] = k; 104ad540459SPierre Jolivet for (b = 0; b < bs; b++) xp[b] = min[b] + ijk[b] * dx[b]; 1050e2ec84fSDave May for (b = 0; b < bs; b++) { 106c448b993SMatthew G. Knepley if (xp[b] < lmin[b]) point_inside = PETSC_FALSE; 107c448b993SMatthew G. Knepley if (xp[b] > lmax[b]) point_inside = PETSC_FALSE; 1080e2ec84fSDave May } 1090e2ec84fSDave May if (point_inside) { 110ad540459SPierre Jolivet for (b = 0; b < bs; b++) _pos[bs * n_estimate + b] = xp[b]; 1110e2ec84fSDave May n_estimate++; 1120e2ec84fSDave May } 1130e2ec84fSDave May } 1140e2ec84fSDave May } 1150e2ec84fSDave May } 1169566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pos, &_pos)); 1170e2ec84fSDave May 1180e2ec84fSDave May /* locate points */ 1199566063dSJacob Faibussowitsch PetscCall(DMLocatePoints(celldm, pos, DM_POINTLOCATION_NONE, &sfcell)); 1209566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell)); 1210e2ec84fSDave May n_found = 0; 1220e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 123ad540459SPierre Jolivet if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) n_found++; 1240e2ec84fSDave May } 1250e2ec84fSDave May 1260e2ec84fSDave May /* adjust size */ 1270e2ec84fSDave May if (mode == ADD_VALUES) { 1289566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &n_curr)); 1290e2ec84fSDave May n_new_est = n_curr + n_found; 1309566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 1310e2ec84fSDave May } 1320e2ec84fSDave May if (mode == INSERT_VALUES) { 1330e2ec84fSDave May n_curr = 0; 1340e2ec84fSDave May n_new_est = n_found; 1359566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 1360e2ec84fSDave May } 1370e2ec84fSDave May 1380e2ec84fSDave May /* initialize new coords, cell owners, pid */ 1399566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pos, &_coor)); 1409566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 1419566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 1420e2ec84fSDave May n_found = 0; 1430e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 1440e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 145ad540459SPierre Jolivet for (b = 0; b < bs; b++) swarm_coor[bs * (n_curr + n_found) + b] = PetscRealPart(_coor[bs * p + b]); 1460e2ec84fSDave May swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 1470e2ec84fSDave May n_found++; 1480e2ec84fSDave May } 1490e2ec84fSDave May } 1509566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 1519566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 1529566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pos, &_coor)); 1530e2ec84fSDave May 1549566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfcell)); 1559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pos)); 1563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1570e2ec84fSDave May } 1580e2ec84fSDave May 159cc4c1da9SBarry Smith /*@ 16020f4b53cSBarry Smith DMSwarmSetPointCoordinates - Set point coordinates in a `DMSWARM` from a user defined list 1610e2ec84fSDave May 16220f4b53cSBarry Smith Collective 1630e2ec84fSDave May 16460225df5SJacob Faibussowitsch Input Parameters: 16520f4b53cSBarry Smith + dm - the `DMSWARM` 1660e2ec84fSDave May . npoints - the number of points to insert 1670e2ec84fSDave May . coor - the coordinate values 16820f4b53cSBarry Smith . redundant - if set to `PETSC_TRUE`, it is assumed that `npoints` and `coor` are only valid on rank 0 and should be broadcast to other ranks 16920f4b53cSBarry Smith - mode - indicates whether to append points to the swarm (`ADD_VALUES`), or over-ride existing points (`INSERT_VALUES`) 1700e2ec84fSDave May 1710e2ec84fSDave May Level: beginner 1720e2ec84fSDave May 1730e2ec84fSDave May Notes: 17420f4b53cSBarry Smith If the user has specified `redundant` as `PETSC_FALSE`, the cell `DM` will attempt to locate the coordinates provided by `coor` within 17520f4b53cSBarry Smith its sub-domain. If they any values within `coor` are not located in the sub-domain, they will be ignored and will not get 17620f4b53cSBarry Smith added to the `DMSWARM`. 1770e2ec84fSDave May 17820f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType`, `DMSwarmSetPointsUniformCoordinates()` 1790e2ec84fSDave May @*/ 180cc4c1da9SBarry Smith PetscErrorCode DMSwarmSetPointCoordinates(DM dm, PetscInt npoints, PetscReal coor[], PetscBool redundant, InsertMode mode) 181d71ae5a4SJacob Faibussowitsch { 1820e2ec84fSDave May PetscReal gmin[] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL}; 1830e2ec84fSDave May PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL}; 1840e2ec84fSDave May PetscInt i, N, bs, b, n_estimate, n_curr, n_new_est, p, n_found; 1850e2ec84fSDave May Vec coorlocal; 1860e2ec84fSDave May const PetscScalar *_coor; 1870e2ec84fSDave May DM celldm; 1880e2ec84fSDave May Vec pos; 1890e2ec84fSDave May PetscScalar *_pos; 1900e2ec84fSDave May PetscReal *swarm_coor; 1910e2ec84fSDave May PetscInt *swarm_cellid; 1920e2ec84fSDave May PetscSF sfcell = NULL; 1930e2ec84fSDave May const PetscSFNode *LA_sfcell; 1940e2ec84fSDave May PetscReal *my_coor; 1950e2ec84fSDave May PetscInt my_npoints; 1960e2ec84fSDave May PetscMPIInt rank; 1970e2ec84fSDave May MPI_Comm comm; 1980e2ec84fSDave May 1990e2ec84fSDave May PetscFunctionBegin; 2000e2ec84fSDave May DMSWARMPICVALID(dm); 2019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 2029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 2030e2ec84fSDave May 2049566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 2059566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(celldm, &coorlocal)); 2069566063dSJacob Faibussowitsch PetscCall(VecGetSize(coorlocal, &N)); 2079566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(coorlocal, &bs)); 2080e2ec84fSDave May N = N / bs; 2099566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coorlocal, &_coor)); 2100e2ec84fSDave May for (i = 0; i < N; i++) { 2110e2ec84fSDave May for (b = 0; b < bs; b++) { 212a5f152d1SDave May gmin[b] = PetscMin(gmin[b], PetscRealPart(_coor[bs * i + b])); 213a5f152d1SDave May gmax[b] = PetscMax(gmax[b], PetscRealPart(_coor[bs * i + b])); 2140e2ec84fSDave May } 2150e2ec84fSDave May } 2169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coorlocal, &_coor)); 2170e2ec84fSDave May 2180e2ec84fSDave May /* broadcast points from rank 0 if requested */ 2190e2ec84fSDave May if (redundant) { 220*6497c311SBarry Smith PetscMPIInt imy; 221*6497c311SBarry Smith 2220e2ec84fSDave May my_npoints = npoints; 2239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&my_npoints, 1, MPIU_INT, 0, comm)); 2240e2ec84fSDave May 2250e2ec84fSDave May if (rank > 0) { /* allocate space */ 2269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(bs * my_npoints, &my_coor)); 2270e2ec84fSDave May } else { 2280e2ec84fSDave May my_coor = coor; 2290e2ec84fSDave May } 230*6497c311SBarry Smith PetscCall(PetscMPIIntCast(bs * my_npoints, &imy)); 231*6497c311SBarry Smith PetscCallMPI(MPI_Bcast(my_coor, imy, MPIU_REAL, 0, comm)); 2320e2ec84fSDave May } else { 2330e2ec84fSDave May my_npoints = npoints; 2340e2ec84fSDave May my_coor = coor; 2350e2ec84fSDave May } 2360e2ec84fSDave May 2370e2ec84fSDave May /* determine the number of points living in the bounding box */ 2380e2ec84fSDave May n_estimate = 0; 2390e2ec84fSDave May for (i = 0; i < my_npoints; i++) { 2400e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 2410e2ec84fSDave May 2420e2ec84fSDave May for (b = 0; b < bs; b++) { 243ad540459SPierre Jolivet if (my_coor[bs * i + b] < gmin[b]) point_inside = PETSC_FALSE; 244ad540459SPierre Jolivet if (my_coor[bs * i + b] > gmax[b]) point_inside = PETSC_FALSE; 2450e2ec84fSDave May } 246ad540459SPierre Jolivet if (point_inside) n_estimate++; 2470e2ec84fSDave May } 2480e2ec84fSDave May 2490e2ec84fSDave May /* create candidate list */ 2509566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &pos)); 2519566063dSJacob Faibussowitsch PetscCall(VecSetSizes(pos, bs * n_estimate, PETSC_DECIDE)); 2529566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(pos, bs)); 2539566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(pos)); 2549566063dSJacob Faibussowitsch PetscCall(VecGetArray(pos, &_pos)); 2550e2ec84fSDave May 2560e2ec84fSDave May n_estimate = 0; 2570e2ec84fSDave May for (i = 0; i < my_npoints; i++) { 2580e2ec84fSDave May PetscBool point_inside = PETSC_TRUE; 2590e2ec84fSDave May 2600e2ec84fSDave May for (b = 0; b < bs; b++) { 261ad540459SPierre Jolivet if (my_coor[bs * i + b] < gmin[b]) point_inside = PETSC_FALSE; 262ad540459SPierre Jolivet if (my_coor[bs * i + b] > gmax[b]) point_inside = PETSC_FALSE; 2630e2ec84fSDave May } 2640e2ec84fSDave May if (point_inside) { 265ad540459SPierre Jolivet for (b = 0; b < bs; b++) _pos[bs * n_estimate + b] = my_coor[bs * i + b]; 2660e2ec84fSDave May n_estimate++; 2670e2ec84fSDave May } 2680e2ec84fSDave May } 2699566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(pos, &_pos)); 2700e2ec84fSDave May 2710e2ec84fSDave May /* locate points */ 2729566063dSJacob Faibussowitsch PetscCall(DMLocatePoints(celldm, pos, DM_POINTLOCATION_NONE, &sfcell)); 2730e2ec84fSDave May 2749566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell)); 2750e2ec84fSDave May n_found = 0; 2760e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 277ad540459SPierre Jolivet if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) n_found++; 2780e2ec84fSDave May } 2790e2ec84fSDave May 2800e2ec84fSDave May /* adjust size */ 2810e2ec84fSDave May if (mode == ADD_VALUES) { 2829566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &n_curr)); 2830e2ec84fSDave May n_new_est = n_curr + n_found; 2849566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 2850e2ec84fSDave May } 2860e2ec84fSDave May if (mode == INSERT_VALUES) { 2870e2ec84fSDave May n_curr = 0; 2880e2ec84fSDave May n_new_est = n_found; 2899566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(dm, n_new_est, -1)); 2900e2ec84fSDave May } 2910e2ec84fSDave May 2920e2ec84fSDave May /* initialize new coords, cell owners, pid */ 2939566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(pos, &_coor)); 2949566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 2959566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 2960e2ec84fSDave May n_found = 0; 2970e2ec84fSDave May for (p = 0; p < n_estimate; p++) { 2980e2ec84fSDave May if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) { 299ad540459SPierre Jolivet for (b = 0; b < bs; b++) swarm_coor[bs * (n_curr + n_found) + b] = PetscRealPart(_coor[bs * p + b]); 3000e2ec84fSDave May swarm_cellid[n_curr + n_found] = LA_sfcell[p].index; 3010e2ec84fSDave May n_found++; 3020e2ec84fSDave May } 3030e2ec84fSDave May } 3049566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 3059566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor)); 3069566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(pos, &_coor)); 3070e2ec84fSDave May 3080e2ec84fSDave May if (redundant) { 30948a46eb9SPierre Jolivet if (rank > 0) PetscCall(PetscFree(my_coor)); 3100e2ec84fSDave May } 3119566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfcell)); 3129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&pos)); 3133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3140e2ec84fSDave May } 3150e2ec84fSDave May 3160e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM, DM, DMSwarmPICLayoutType, PetscInt); 3170e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM, DM, DMSwarmPICLayoutType, PetscInt); 3180e2ec84fSDave May 319cc4c1da9SBarry Smith /*@ 3200e2ec84fSDave May DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell 3210e2ec84fSDave May 32220f4b53cSBarry Smith Not Collective 3230e2ec84fSDave May 32460225df5SJacob Faibussowitsch Input Parameters: 32520f4b53cSBarry Smith + dm - the `DMSWARM` 32620f4b53cSBarry Smith . layout_type - method used to fill each cell with the cell `DM` 3270e2ec84fSDave May - fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type) 3280e2ec84fSDave May 3290e2ec84fSDave May Level: beginner 3300e2ec84fSDave May 3310e2ec84fSDave May Notes: 33220f4b53cSBarry Smith The insert method will reset any previous defined points within the `DMSWARM`. 333e7af74c8SDave May 33420f4b53cSBarry Smith When using a `DMDA` both 2D and 3D are supported for all layout types provided you are using `DMDA_ELEMENT_Q1`. 335e7af74c8SDave May 336a4e35b19SJacob Faibussowitsch When using a `DMPLEX` the following case are supported\: 33720f4b53cSBarry Smith .vb 338ea3d7275SDave May (i) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle), 339ea3d7275SDave May (ii) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex, 340ea3d7275SDave May (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri. 34120f4b53cSBarry Smith .ve 3420e2ec84fSDave May 34320f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmPICLayoutType`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType` 3440e2ec84fSDave May @*/ 345cc4c1da9SBarry Smith PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm, DMSwarmPICLayoutType layout_type, PetscInt fill_param) 346d71ae5a4SJacob Faibussowitsch { 3470e2ec84fSDave May DM celldm; 3480e2ec84fSDave May PetscBool isDA, isPLEX; 3490e2ec84fSDave May 3500e2ec84fSDave May PetscFunctionBegin; 3510e2ec84fSDave May DMSWARMPICVALID(dm); 3529566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 3539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMDA, &isDA)); 3549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMPLEX, &isPLEX)); 3550e2ec84fSDave May if (isDA) { 3569566063dSJacob Faibussowitsch PetscCall(private_DMSwarmInsertPointsUsingCellDM_DA(dm, celldm, layout_type, fill_param)); 3570e2ec84fSDave May } else if (isPLEX) { 3589566063dSJacob Faibussowitsch PetscCall(private_DMSwarmInsertPointsUsingCellDM_PLEX(dm, celldm, layout_type, fill_param)); 3590e2ec84fSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only supported for cell DMs of type DMDA and DMPLEX"); 3603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3610e2ec84fSDave May } 3620e2ec84fSDave May 363431382f2SDave May extern PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM, DM, PetscInt, PetscReal *); 364431382f2SDave May 365431382f2SDave May /*@C 366431382f2SDave May DMSwarmSetPointCoordinatesCellwise - Insert point coordinates (defined over the reference cell) within each cell 367431382f2SDave May 36820f4b53cSBarry Smith Not Collective 369431382f2SDave May 37060225df5SJacob Faibussowitsch Input Parameters: 37120f4b53cSBarry Smith + dm - the `DMSWARM` 372431382f2SDave May . npoints - the number of points to insert in each cell 373431382f2SDave May - xi - the coordinates (defined in the local coordinate system for each cell) to insert 374431382f2SDave May 375431382f2SDave May Level: beginner 376431382f2SDave May 377431382f2SDave May Notes: 37820f4b53cSBarry Smith The method will reset any previous defined points within the `DMSWARM`. 37920f4b53cSBarry Smith Only supported for `DMPLEX`. If you are using a `DMDA` it is recommended to either use 38020f4b53cSBarry Smith `DMSwarmInsertPointsUsingCellDM()`, or extract and set the coordinates yourself the following code 38120f4b53cSBarry Smith .vb 38220f4b53cSBarry Smith PetscReal *coor; 38320f4b53cSBarry Smith DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 38420f4b53cSBarry Smith // user code to define the coordinates here 38520f4b53cSBarry Smith DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor); 38620f4b53cSBarry Smith .ve 387e7af74c8SDave May 38820f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetCellDM()`, `DMSwarmInsertPointsUsingCellDM()` 389431382f2SDave May @*/ 390cc4c1da9SBarry Smith PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm, PetscInt npoints, PetscReal xi[]) 391d71ae5a4SJacob Faibussowitsch { 392431382f2SDave May DM celldm; 393431382f2SDave May PetscBool isDA, isPLEX; 394431382f2SDave May 3950e2ec84fSDave May PetscFunctionBegin; 396431382f2SDave May DMSWARMPICVALID(dm); 3979566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 3989566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMDA, &isDA)); 3999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMPLEX, &isPLEX)); 40028b400f6SJacob Faibussowitsch PetscCheck(!isDA, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()"); 401f7d195e4SLawrence Mitchell if (isPLEX) { 4029566063dSJacob Faibussowitsch PetscCall(private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm, celldm, npoints, xi)); 403431382f2SDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only supported for cell DMs of type DMDA and DMPLEX"); 4043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4050e2ec84fSDave May } 406431382f2SDave May 407cc4c1da9SBarry Smith /*@ 408b799feefSDave May DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM 4090e2ec84fSDave May 41020f4b53cSBarry Smith Not Collective 4110e2ec84fSDave May 41260225df5SJacob Faibussowitsch Input Parameter: 41320f4b53cSBarry Smith . dm - the `DMSWARM` 4140e2ec84fSDave May 41560225df5SJacob Faibussowitsch Output Parameters: 41620f4b53cSBarry Smith + ncells - the number of cells in the cell `DM` (optional argument, pass `NULL` to ignore) 417b799feefSDave May - count - array of length ncells containing the number of points per cell 4180e2ec84fSDave May 4190e2ec84fSDave May Level: beginner 4200e2ec84fSDave May 4210e2ec84fSDave May Notes: 4220e2ec84fSDave May The array count is allocated internally and must be free'd by the user. 4230e2ec84fSDave May 42420f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetType()`, `DMSwarmSetCellDM()`, `DMSwarmType` 4250e2ec84fSDave May @*/ 426cc4c1da9SBarry Smith PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm, PetscInt *ncells, PetscInt **count) 427d71ae5a4SJacob Faibussowitsch { 428b799feefSDave May PetscBool isvalid; 429b799feefSDave May PetscInt nel; 430b799feefSDave May PetscInt *sum; 431b799feefSDave May 4320e2ec84fSDave May PetscFunctionBegin; 4339566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetIsValid(dm, &isvalid)); 434b799feefSDave May nel = 0; 435b799feefSDave May if (isvalid) { 436b799feefSDave May PetscInt e; 437b799feefSDave May 4389566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetSizes(dm, &nel, NULL)); 439b799feefSDave May 4409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nel, &sum)); 44148a46eb9SPierre Jolivet for (e = 0; e < nel; e++) PetscCall(DMSwarmSortGetNumberOfPointsPerCell(dm, e, &sum[e])); 442b799feefSDave May } else { 443b799feefSDave May DM celldm; 444b799feefSDave May PetscBool isda, isplex, isshell; 445b799feefSDave May PetscInt p, npoints; 446b799feefSDave May PetscInt *swarm_cellid; 447b799feefSDave May 448b799feefSDave May /* get the number of cells */ 4499566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(dm, &celldm)); 4509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMDA, &isda)); 4519566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMPLEX, &isplex)); 4529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)celldm, DMSHELL, &isshell)); 453b799feefSDave May if (isda) { 454b799feefSDave May PetscInt _nel, _npe; 455b799feefSDave May const PetscInt *_element; 456b799feefSDave May 4579566063dSJacob Faibussowitsch PetscCall(DMDAGetElements(celldm, &_nel, &_npe, &_element)); 458b799feefSDave May nel = _nel; 4599566063dSJacob Faibussowitsch PetscCall(DMDARestoreElements(celldm, &_nel, &_npe, &_element)); 460b799feefSDave May } else if (isplex) { 461b799feefSDave May PetscInt ps, pe; 462b799feefSDave May 4639566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(celldm, 0, &ps, &pe)); 464b799feefSDave May nel = pe - ps; 465b799feefSDave May } else if (isshell) { 466b799feefSDave May PetscErrorCode (*method_DMShellGetNumberOfCells)(DM, PetscInt *); 467b799feefSDave May 4689566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)celldm, "DMGetNumberOfCells_C", &method_DMShellGetNumberOfCells)); 469b799feefSDave May if (method_DMShellGetNumberOfCells) { 4709566063dSJacob Faibussowitsch PetscCall(method_DMShellGetNumberOfCells(celldm, &nel)); 4719371c9d4SSatish Balay } else 4729371c9d4SSatish Balay SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot determine the number of cells for the DMSHELL object. User must provide a method via PetscObjectComposeFunction( (PetscObject)shelldm, \"DMGetNumberOfCells_C\", your_function_to_compute_number_of_cells);"); 473b799feefSDave May } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot determine the number of cells for a DM not of type DA, PLEX or SHELL"); 474b799feefSDave May 4759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nel, &sum)); 4769566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(sum, nel)); 4779566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(dm, &npoints)); 4789566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 479b799feefSDave May for (p = 0; p < npoints; p++) { 480ad540459SPierre Jolivet if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) sum[swarm_cellid[p]]++; 481b799feefSDave May } 4829566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid)); 483b799feefSDave May } 484ad540459SPierre Jolivet if (ncells) *ncells = nel; 485b799feefSDave May *count = sum; 4863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4870e2ec84fSDave May } 48835b38c60SMatthew G. Knepley 48935b38c60SMatthew G. Knepley /*@ 49035b38c60SMatthew G. Knepley DMSwarmGetNumSpecies - Get the number of particle species 49135b38c60SMatthew G. Knepley 49220f4b53cSBarry Smith Not Collective 49335b38c60SMatthew G. Knepley 49460225df5SJacob Faibussowitsch Input Parameter: 49560225df5SJacob Faibussowitsch . sw - the `DMSWARM` 49635b38c60SMatthew G. Knepley 49760225df5SJacob Faibussowitsch Output Parameters: 49835b38c60SMatthew G. Knepley . Ns - the number of species 49935b38c60SMatthew G. Knepley 50035b38c60SMatthew G. Knepley Level: intermediate 50135b38c60SMatthew G. Knepley 50220f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmSetNumSpecies()`, `DMSwarmSetType()`, `DMSwarmType` 50335b38c60SMatthew G. Knepley @*/ 504d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmGetNumSpecies(DM sw, PetscInt *Ns) 505d71ae5a4SJacob Faibussowitsch { 50635b38c60SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 50735b38c60SMatthew G. Knepley 50835b38c60SMatthew G. Knepley PetscFunctionBegin; 50935b38c60SMatthew G. Knepley *Ns = swarm->Ns; 5103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 51135b38c60SMatthew G. Knepley } 51235b38c60SMatthew G. Knepley 51335b38c60SMatthew G. Knepley /*@ 51435b38c60SMatthew G. Knepley DMSwarmSetNumSpecies - Set the number of particle species 51535b38c60SMatthew G. Knepley 51620f4b53cSBarry Smith Not Collective 51735b38c60SMatthew G. Knepley 51860225df5SJacob Faibussowitsch Input Parameters: 51960225df5SJacob Faibussowitsch + sw - the `DMSWARM` 52035b38c60SMatthew G. Knepley - Ns - the number of species 52135b38c60SMatthew G. Knepley 52235b38c60SMatthew G. Knepley Level: intermediate 52335b38c60SMatthew G. Knepley 52420f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmGetNumSpecies()`, `DMSwarmSetType()`, `DMSwarmType` 52535b38c60SMatthew G. Knepley @*/ 526d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmSetNumSpecies(DM sw, PetscInt Ns) 527d71ae5a4SJacob Faibussowitsch { 52835b38c60SMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 52935b38c60SMatthew G. Knepley 53035b38c60SMatthew G. Knepley PetscFunctionBegin; 53135b38c60SMatthew G. Knepley swarm->Ns = Ns; 5323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53335b38c60SMatthew G. Knepley } 53435b38c60SMatthew G. Knepley 53535b38c60SMatthew G. Knepley /*@C 5366c5a79ebSMatthew G. Knepley DMSwarmGetCoordinateFunction - Get the function setting initial particle positions, if it exists 5376c5a79ebSMatthew G. Knepley 53820f4b53cSBarry Smith Not Collective 5396c5a79ebSMatthew G. Knepley 54060225df5SJacob Faibussowitsch Input Parameter: 54160225df5SJacob Faibussowitsch . sw - the `DMSWARM` 5426c5a79ebSMatthew G. Knepley 5436c5a79ebSMatthew G. Knepley Output Parameter: 5448434afd1SBarry Smith . coordFunc - the function setting initial particle positions, or `NULL`, see `PetscSimplePointFn` for the calling sequence 5456c5a79ebSMatthew G. Knepley 5466c5a79ebSMatthew G. Knepley Level: intermediate 5476c5a79ebSMatthew G. Knepley 5488434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmSetCoordinateFunction()`, `DMSwarmGetVelocityFunction()`, `DMSwarmInitializeCoordinates()`, `PetscSimplePointFn` 5496c5a79ebSMatthew G. Knepley @*/ 5508434afd1SBarry Smith PetscErrorCode DMSwarmGetCoordinateFunction(DM sw, PetscSimplePointFn **coordFunc) 551d71ae5a4SJacob Faibussowitsch { 5526c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 5536c5a79ebSMatthew G. Knepley 5546c5a79ebSMatthew G. Knepley PetscFunctionBegin; 5556c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 5564f572ea9SToby Isaac PetscAssertPointer(coordFunc, 2); 5576c5a79ebSMatthew G. Knepley *coordFunc = swarm->coordFunc; 5583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5596c5a79ebSMatthew G. Knepley } 5606c5a79ebSMatthew G. Knepley 5616c5a79ebSMatthew G. Knepley /*@C 5626c5a79ebSMatthew G. Knepley DMSwarmSetCoordinateFunction - Set the function setting initial particle positions 5636c5a79ebSMatthew G. Knepley 56420f4b53cSBarry Smith Not Collective 5656c5a79ebSMatthew G. Knepley 56660225df5SJacob Faibussowitsch Input Parameters: 56760225df5SJacob Faibussowitsch + sw - the `DMSWARM` 5688434afd1SBarry Smith - coordFunc - the function setting initial particle positions, see `PetscSimplePointFn` for the calling sequence 5696c5a79ebSMatthew G. Knepley 5706c5a79ebSMatthew G. Knepley Level: intermediate 5716c5a79ebSMatthew G. Knepley 5728434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmGetCoordinateFunction()`, `DMSwarmSetVelocityFunction()`, `DMSwarmInitializeCoordinates()`, `PetscSimplePointFn` 5736c5a79ebSMatthew G. Knepley @*/ 5748434afd1SBarry Smith PetscErrorCode DMSwarmSetCoordinateFunction(DM sw, PetscSimplePointFn *coordFunc) 575d71ae5a4SJacob Faibussowitsch { 5766c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 5776c5a79ebSMatthew G. Knepley 5786c5a79ebSMatthew G. Knepley PetscFunctionBegin; 5796c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 5806c5a79ebSMatthew G. Knepley PetscValidFunction(coordFunc, 2); 5816c5a79ebSMatthew G. Knepley swarm->coordFunc = coordFunc; 5823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5836c5a79ebSMatthew G. Knepley } 5846c5a79ebSMatthew G. Knepley 5856c5a79ebSMatthew G. Knepley /*@C 58660225df5SJacob Faibussowitsch DMSwarmGetVelocityFunction - Get the function setting initial particle velocities, if it exists 5876c5a79ebSMatthew G. Knepley 58820f4b53cSBarry Smith Not Collective 5896c5a79ebSMatthew G. Knepley 59060225df5SJacob Faibussowitsch Input Parameter: 59160225df5SJacob Faibussowitsch . sw - the `DMSWARM` 5926c5a79ebSMatthew G. Knepley 5936c5a79ebSMatthew G. Knepley Output Parameter: 5948434afd1SBarry Smith . velFunc - the function setting initial particle velocities, or `NULL`, see `PetscSimplePointFn` for the calling sequence 5956c5a79ebSMatthew G. Knepley 5966c5a79ebSMatthew G. Knepley Level: intermediate 5976c5a79ebSMatthew G. Knepley 5988434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmSetVelocityFunction()`, `DMSwarmGetCoordinateFunction()`, `DMSwarmInitializeVelocities()`, `PetscSimplePointFn` 5996c5a79ebSMatthew G. Knepley @*/ 6008434afd1SBarry Smith PetscErrorCode DMSwarmGetVelocityFunction(DM sw, PetscSimplePointFn **velFunc) 601d71ae5a4SJacob Faibussowitsch { 6026c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 6036c5a79ebSMatthew G. Knepley 6046c5a79ebSMatthew G. Knepley PetscFunctionBegin; 6056c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 6064f572ea9SToby Isaac PetscAssertPointer(velFunc, 2); 6076c5a79ebSMatthew G. Knepley *velFunc = swarm->velFunc; 6083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6096c5a79ebSMatthew G. Knepley } 6106c5a79ebSMatthew G. Knepley 6116c5a79ebSMatthew G. Knepley /*@C 6126c5a79ebSMatthew G. Knepley DMSwarmSetVelocityFunction - Set the function setting initial particle velocities 6136c5a79ebSMatthew G. Knepley 61420f4b53cSBarry Smith Not Collective 6156c5a79ebSMatthew G. Knepley 61660225df5SJacob Faibussowitsch Input Parameters: 617a4e35b19SJacob Faibussowitsch + sw - the `DMSWARM` 6188434afd1SBarry Smith - velFunc - the function setting initial particle velocities, see `PetscSimplePointFn` for the calling sequence 6196c5a79ebSMatthew G. Knepley 6206c5a79ebSMatthew G. Knepley Level: intermediate 6216c5a79ebSMatthew G. Knepley 6228434afd1SBarry Smith .seealso: `DMSWARM`, `DMSwarmGetVelocityFunction()`, `DMSwarmSetCoordinateFunction()`, `DMSwarmInitializeVelocities()`, `PetscSimplePointFn` 6236c5a79ebSMatthew G. Knepley @*/ 6248434afd1SBarry Smith PetscErrorCode DMSwarmSetVelocityFunction(DM sw, PetscSimplePointFn *velFunc) 625d71ae5a4SJacob Faibussowitsch { 6266c5a79ebSMatthew G. Knepley DM_Swarm *swarm = (DM_Swarm *)sw->data; 6276c5a79ebSMatthew G. Knepley 6286c5a79ebSMatthew G. Knepley PetscFunctionBegin; 6296c5a79ebSMatthew G. Knepley PetscValidHeaderSpecific(sw, DM_CLASSID, 1); 6306c5a79ebSMatthew G. Knepley PetscValidFunction(velFunc, 2); 6316c5a79ebSMatthew G. Knepley swarm->velFunc = velFunc; 6323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6336c5a79ebSMatthew G. Knepley } 6346c5a79ebSMatthew G. Knepley 6356c5a79ebSMatthew G. Knepley /*@C 63635b38c60SMatthew G. Knepley DMSwarmComputeLocalSize - Compute the local number and distribution of particles based upon a density function 63735b38c60SMatthew G. Knepley 63820f4b53cSBarry Smith Not Collective 63935b38c60SMatthew G. Knepley 64035b38c60SMatthew G. Knepley Input Parameters: 64120f4b53cSBarry Smith + sw - The `DMSWARM` 64235b38c60SMatthew G. Knepley . N - The target number of particles 64335b38c60SMatthew G. Knepley - density - The density field for the particle layout, normalized to unity 64435b38c60SMatthew G. Knepley 64535b38c60SMatthew G. Knepley Level: advanced 64635b38c60SMatthew G. Knepley 64720f4b53cSBarry Smith Note: 64820f4b53cSBarry Smith One particle will be created for each species. 64920f4b53cSBarry Smith 65020f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSizeFromOptions()` 65135b38c60SMatthew G. Knepley @*/ 652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmComputeLocalSize(DM sw, PetscInt N, PetscProbFunc density) 653d71ae5a4SJacob Faibussowitsch { 65435b38c60SMatthew G. Knepley DM dm; 65535b38c60SMatthew G. Knepley PetscQuadrature quad; 65635b38c60SMatthew G. Knepley const PetscReal *xq, *wq; 657ea7032a0SMatthew G. Knepley PetscReal *n_int; 658ea7032a0SMatthew G. Knepley PetscInt *npc_s, *cellid, Ni; 659ea7032a0SMatthew G. Knepley PetscReal gmin[3], gmax[3], xi0[3]; 660ea7032a0SMatthew G. Knepley PetscInt Ns, cStart, cEnd, c, dim, d, Nq, q, Np = 0, p, s; 66135b38c60SMatthew G. Knepley PetscBool simplex; 66235b38c60SMatthew G. Knepley 66335b38c60SMatthew G. Knepley PetscFunctionBegin; 6649566063dSJacob Faibussowitsch PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 6659566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(sw, &dm)); 6669566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 667ea7032a0SMatthew G. Knepley PetscCall(DMGetBoundingBox(dm, gmin, gmax)); 6689566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 6699566063dSJacob Faibussowitsch PetscCall(DMPlexIsSimplex(dm, &simplex)); 6706858538eSMatthew G. Knepley PetscCall(DMGetCoordinatesLocalSetUp(dm)); 6719566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscDTStroudConicalQuadrature(dim, 1, 5, -1.0, 1.0, &quad)); 6729566063dSJacob Faibussowitsch else PetscCall(PetscDTGaussTensorQuadrature(dim, 1, 5, -1.0, 1.0, &quad)); 6739566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, &xq, &wq)); 674ea7032a0SMatthew G. Knepley PetscCall(PetscCalloc2(Ns, &n_int, (cEnd - cStart) * Ns, &npc_s)); 67535b38c60SMatthew G. Knepley /* Integrate the density function to get the number of particles in each cell */ 67635b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 67735b38c60SMatthew G. Knepley for (c = 0; c < cEnd - cStart; ++c) { 67835b38c60SMatthew G. Knepley const PetscInt cell = c + cStart; 679ea7032a0SMatthew G. Knepley PetscReal v0[3], J[9], invJ[9], detJ, detJp = 2. / (gmax[0] - gmin[0]), xr[3], den; 68035b38c60SMatthew G. Knepley 681ea7032a0SMatthew G. Knepley /* Have to transform quadrature points/weights to cell domain */ 6829566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, invJ, &detJ)); 683ea7032a0SMatthew G. Knepley PetscCall(PetscArrayzero(n_int, Ns)); 68435b38c60SMatthew G. Knepley for (q = 0; q < Nq; ++q) { 68535b38c60SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, &xq[q * dim], xr); 686ea7032a0SMatthew G. Knepley /* Have to transform mesh to domain of definition of PDF, [-1, 1], and weight PDF by |J|/2 */ 687ea7032a0SMatthew G. Knepley xr[0] = detJp * (xr[0] - gmin[0]) - 1.; 688ea7032a0SMatthew G. Knepley 689ea7032a0SMatthew G. Knepley for (s = 0; s < Ns; ++s) { 690ea7032a0SMatthew G. Knepley PetscCall(density(xr, NULL, &den)); 691ea7032a0SMatthew G. Knepley n_int[s] += (detJp * den) * (detJ * wq[q]) / (PetscReal)Ns; 69235b38c60SMatthew G. Knepley } 693ea7032a0SMatthew G. Knepley } 694ea7032a0SMatthew G. Knepley for (s = 0; s < Ns; ++s) { 695ea7032a0SMatthew G. Knepley Ni = N; 696ea7032a0SMatthew G. Knepley npc_s[c * Ns + s] += (PetscInt)(Ni * n_int[s]); 697ea7032a0SMatthew G. Knepley Np += npc_s[c * Ns + s]; 698ea7032a0SMatthew G. Knepley } 69935b38c60SMatthew G. Knepley } 7009566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&quad)); 7019566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(sw, Np, 0)); 7029566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **)&cellid)); 70335b38c60SMatthew G. Knepley for (c = 0, p = 0; c < cEnd - cStart; ++c) { 704ea7032a0SMatthew G. Knepley for (s = 0; s < Ns; ++s) { 705ea7032a0SMatthew G. Knepley for (q = 0; q < npc_s[c * Ns + s]; ++q, ++p) cellid[p] = c; 706ea7032a0SMatthew G. Knepley } 70735b38c60SMatthew G. Knepley } 7089566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **)&cellid)); 709ea7032a0SMatthew G. Knepley PetscCall(PetscFree2(n_int, npc_s)); 7103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71135b38c60SMatthew G. Knepley } 71235b38c60SMatthew G. Knepley 71335b38c60SMatthew G. Knepley /*@ 71435b38c60SMatthew G. Knepley DMSwarmComputeLocalSizeFromOptions - Compute the local number and distribution of particles based upon a density function determined by options 71535b38c60SMatthew G. Knepley 71620f4b53cSBarry Smith Not Collective 71735b38c60SMatthew G. Knepley 7182fe279fdSBarry Smith Input Parameter: 7192fe279fdSBarry Smith . sw - The `DMSWARM` 72035b38c60SMatthew G. Knepley 72135b38c60SMatthew G. Knepley Level: advanced 72235b38c60SMatthew G. Knepley 72320f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()` 72435b38c60SMatthew G. Knepley @*/ 725d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmComputeLocalSizeFromOptions(DM sw) 726d71ae5a4SJacob Faibussowitsch { 72735b38c60SMatthew G. Knepley PetscProbFunc pdf; 72835b38c60SMatthew G. Knepley const char *prefix; 7296c5a79ebSMatthew G. Knepley char funcname[PETSC_MAX_PATH_LEN]; 7306c5a79ebSMatthew G. Knepley PetscInt *N, Ns, dim, n; 7316c5a79ebSMatthew G. Knepley PetscBool flg; 7326c5a79ebSMatthew G. Knepley PetscMPIInt size, rank; 73335b38c60SMatthew G. Knepley 73435b38c60SMatthew G. Knepley PetscFunctionBegin; 7356c5a79ebSMatthew G. Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)sw), &size)); 7366c5a79ebSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)sw), &rank)); 7376c5a79ebSMatthew G. Knepley PetscCall(PetscCalloc1(size, &N)); 738d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)sw), "", "DMSwarm Options", "DMSWARM"); 7396c5a79ebSMatthew G. Knepley n = size; 7406c5a79ebSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_swarm_num_particles", "The target number of particles", "", N, &n, NULL)); 7416c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 7429566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_swarm_num_species", "The number of species", "DMSwarmSetNumSpecies", Ns, &Ns, &flg)); 7439566063dSJacob Faibussowitsch if (flg) PetscCall(DMSwarmSetNumSpecies(sw, Ns)); 7446c5a79ebSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_swarm_coordinate_function", "Function to determine particle coordinates", "DMSwarmSetCoordinateFunction", funcname, funcname, sizeof(funcname), &flg)); 745d0609cedSBarry Smith PetscOptionsEnd(); 7466c5a79ebSMatthew G. Knepley if (flg) { 7478434afd1SBarry Smith PetscSimplePointFn *coordFunc; 74835b38c60SMatthew G. Knepley 7496c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 7506c5a79ebSMatthew G. Knepley PetscCall(PetscDLSym(NULL, funcname, (void **)&coordFunc)); 7516c5a79ebSMatthew G. Knepley PetscCheck(coordFunc, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "Could not locate function %s", funcname); 7526c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 7536c5a79ebSMatthew G. Knepley PetscCall(DMSwarmSetLocalSizes(sw, N[rank] * Ns, 0)); 7546c5a79ebSMatthew G. Knepley PetscCall(DMSwarmSetCoordinateFunction(sw, coordFunc)); 7556c5a79ebSMatthew G. Knepley } else { 7569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 7579566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sw, &prefix)); 7589566063dSJacob Faibussowitsch PetscCall(PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_coordinate_density", &pdf, NULL, NULL)); 7596c5a79ebSMatthew G. Knepley PetscCall(DMSwarmComputeLocalSize(sw, N[rank], pdf)); 7606c5a79ebSMatthew G. Knepley } 7616c5a79ebSMatthew G. Knepley PetscCall(PetscFree(N)); 7623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 76335b38c60SMatthew G. Knepley } 76435b38c60SMatthew G. Knepley 76535b38c60SMatthew G. Knepley /*@ 76635b38c60SMatthew G. Knepley DMSwarmInitializeCoordinates - Determine the initial coordinates of particles for a PIC method 76735b38c60SMatthew G. Knepley 76820f4b53cSBarry Smith Not Collective 76935b38c60SMatthew G. Knepley 77020f4b53cSBarry Smith Input Parameter: 77120f4b53cSBarry Smith . sw - The `DMSWARM` 77235b38c60SMatthew G. Knepley 77335b38c60SMatthew G. Knepley Level: advanced 77435b38c60SMatthew G. Knepley 77520f4b53cSBarry Smith Note: 77620f4b53cSBarry Smith Currently, we randomly place particles in their assigned cell 77720f4b53cSBarry Smith 77820f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()`, `DMSwarmInitializeVelocities()` 77935b38c60SMatthew G. Knepley @*/ 780d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeCoordinates(DM sw) 781d71ae5a4SJacob Faibussowitsch { 7828434afd1SBarry Smith PetscSimplePointFn *coordFunc; 78335b38c60SMatthew G. Knepley PetscScalar *weight; 7846c5a79ebSMatthew G. Knepley PetscReal *x; 78535b38c60SMatthew G. Knepley PetscInt *species; 7866c5a79ebSMatthew G. Knepley void *ctx; 78735b38c60SMatthew G. Knepley PetscBool removePoints = PETSC_TRUE; 78835b38c60SMatthew G. Knepley PetscDataType dtype; 7896c5a79ebSMatthew G. Knepley PetscInt Np, p, Ns, dim, d, bs; 79035b38c60SMatthew G. Knepley 79135b38c60SMatthew G. Knepley PetscFunctionBeginUser; 7926c5a79ebSMatthew G. Knepley PetscCall(DMGetDimension(sw, &dim)); 7936c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetLocalSize(sw, &Np)); 7949566063dSJacob Faibussowitsch PetscCall(DMSwarmGetNumSpecies(sw, &Ns)); 7956c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetCoordinateFunction(sw, &coordFunc)); 7966c5a79ebSMatthew G. Knepley 7976c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, DMSwarmPICField_coor, &bs, &dtype, (void **)&x)); 7986c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "w_q", &bs, &dtype, (void **)&weight)); 7996c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 8006c5a79ebSMatthew G. Knepley if (coordFunc) { 8016c5a79ebSMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 8026c5a79ebSMatthew G. Knepley for (p = 0; p < Np; ++p) { 8036c5a79ebSMatthew G. Knepley PetscScalar X[3]; 8046c5a79ebSMatthew G. Knepley 8056c5a79ebSMatthew G. Knepley PetscCall((*coordFunc)(dim, 0., NULL, p, X, ctx)); 8066c5a79ebSMatthew G. Knepley for (d = 0; d < dim; ++d) x[p * dim + d] = PetscRealPart(X[d]); 8076c5a79ebSMatthew G. Knepley weight[p] = 1.0; 8086c5a79ebSMatthew G. Knepley species[p] = p % Ns; 8096c5a79ebSMatthew G. Knepley } 8106c5a79ebSMatthew G. Knepley } else { 8116c5a79ebSMatthew G. Knepley DM dm; 8126c5a79ebSMatthew G. Knepley PetscRandom rnd; 8136c5a79ebSMatthew G. Knepley PetscReal xi0[3]; 8146c5a79ebSMatthew G. Knepley PetscInt cStart, cEnd, c; 8156c5a79ebSMatthew G. Knepley 8169566063dSJacob Faibussowitsch PetscCall(DMSwarmGetCellDM(sw, &dm)); 8179566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 818ea7032a0SMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 81935b38c60SMatthew G. Knepley 82035b38c60SMatthew G. Knepley /* Set particle position randomly in cell, set weights to 1 */ 8219566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)dm), &rnd)); 8229566063dSJacob Faibussowitsch PetscCall(PetscRandomSetInterval(rnd, -1.0, 1.0)); 8239566063dSJacob Faibussowitsch PetscCall(PetscRandomSetFromOptions(rnd)); 8249566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetAccess(sw)); 82535b38c60SMatthew G. Knepley for (d = 0; d < dim; ++d) xi0[d] = -1.0; 82635b38c60SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 82735b38c60SMatthew G. Knepley PetscReal v0[3], J[9], invJ[9], detJ; 82835b38c60SMatthew G. Knepley PetscInt *pidx, Npc, q; 82935b38c60SMatthew G. Knepley 8309566063dSJacob Faibussowitsch PetscCall(DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx)); 8319566063dSJacob Faibussowitsch PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); 83235b38c60SMatthew G. Knepley for (q = 0; q < Npc; ++q) { 83335b38c60SMatthew G. Knepley const PetscInt p = pidx[q]; 83435b38c60SMatthew G. Knepley PetscReal xref[3]; 83535b38c60SMatthew G. Knepley 8369566063dSJacob Faibussowitsch for (d = 0; d < dim; ++d) PetscCall(PetscRandomGetValueReal(rnd, &xref[d])); 83735b38c60SMatthew G. Knepley CoordinatesRefToReal(dim, dim, xi0, v0, J, xref, &x[p * dim]); 83835b38c60SMatthew G. Knepley 839ea7032a0SMatthew G. Knepley weight[p] = 1.0 / Np; 8406c5a79ebSMatthew G. Knepley species[p] = p % Ns; 84135b38c60SMatthew G. Knepley } 8429566063dSJacob Faibussowitsch PetscCall(PetscFree(pidx)); 84335b38c60SMatthew G. Knepley } 8449566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&rnd)); 8459566063dSJacob Faibussowitsch PetscCall(DMSwarmSortRestoreAccess(sw)); 8466c5a79ebSMatthew G. Knepley } 8479566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **)&x)); 8486c5a79ebSMatthew G. Knepley PetscCall(DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **)&weight)); 8499566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 8506c5a79ebSMatthew G. Knepley 8519566063dSJacob Faibussowitsch PetscCall(DMSwarmMigrate(sw, removePoints)); 8529566063dSJacob Faibussowitsch PetscCall(DMLocalizeCoordinates(sw)); 8533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 85435b38c60SMatthew G. Knepley } 85535b38c60SMatthew G. Knepley 85635b38c60SMatthew G. Knepley /*@C 85735b38c60SMatthew G. Knepley DMSwarmInitializeVelocities - Set the initial velocities of particles using a distribution. 85835b38c60SMatthew G. Knepley 85920f4b53cSBarry Smith Collective 86035b38c60SMatthew G. Knepley 86135b38c60SMatthew G. Knepley Input Parameters: 86220f4b53cSBarry Smith + sw - The `DMSWARM` object 86335b38c60SMatthew G. Knepley . sampler - A function which uniformly samples the velocity PDF 86435b38c60SMatthew G. Knepley - v0 - The velocity scale for nondimensionalization for each species 86535b38c60SMatthew G. Knepley 86635b38c60SMatthew G. Knepley Level: advanced 86735b38c60SMatthew G. Knepley 86820f4b53cSBarry Smith Note: 86920f4b53cSBarry Smith If `v0` is zero for the first species, all velocities are set to zero. If it is zero for any other species, the effect will be to give that species zero velocity. 87020f4b53cSBarry Smith 87120f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()`, `DMSwarmInitializeCoordinates()`, `DMSwarmInitializeVelocitiesFromOptions()` 87235b38c60SMatthew G. Knepley @*/ 873d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeVelocities(DM sw, PetscProbFunc sampler, const PetscReal v0[]) 874d71ae5a4SJacob Faibussowitsch { 8758434afd1SBarry Smith PetscSimplePointFn *velFunc; 87635b38c60SMatthew G. Knepley PetscReal *v; 87735b38c60SMatthew G. Knepley PetscInt *species; 8786c5a79ebSMatthew G. Knepley void *ctx; 87935b38c60SMatthew G. Knepley PetscInt dim, Np, p; 88035b38c60SMatthew G. Knepley 88135b38c60SMatthew G. Knepley PetscFunctionBegin; 8826c5a79ebSMatthew G. Knepley PetscCall(DMSwarmGetVelocityFunction(sw, &velFunc)); 88335b38c60SMatthew G. Knepley 8849566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 8859566063dSJacob Faibussowitsch PetscCall(DMSwarmGetLocalSize(sw, &Np)); 8869566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "velocity", NULL, NULL, (void **)&v)); 8879566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "species", NULL, NULL, (void **)&species)); 8886c5a79ebSMatthew G. Knepley if (v0[0] == 0.) { 8896c5a79ebSMatthew G. Knepley PetscCall(PetscArrayzero(v, Np * dim)); 8906c5a79ebSMatthew G. Knepley } else if (velFunc) { 8916c5a79ebSMatthew G. Knepley PetscCall(DMGetApplicationContext(sw, &ctx)); 8926c5a79ebSMatthew G. Knepley for (p = 0; p < Np; ++p) { 8936c5a79ebSMatthew G. Knepley PetscInt s = species[p], d; 8946c5a79ebSMatthew G. Knepley PetscScalar vel[3]; 8956c5a79ebSMatthew G. Knepley 8966c5a79ebSMatthew G. Knepley PetscCall((*velFunc)(dim, 0., NULL, p, vel, ctx)); 8976c5a79ebSMatthew G. Knepley for (d = 0; d < dim; ++d) v[p * dim + d] = (v0[s] / v0[0]) * PetscRealPart(vel[d]); 8986c5a79ebSMatthew G. Knepley } 8996c5a79ebSMatthew G. Knepley } else { 9006c5a79ebSMatthew G. Knepley PetscRandom rnd; 9016c5a79ebSMatthew G. Knepley 9026c5a79ebSMatthew G. Knepley PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)sw), &rnd)); 9036c5a79ebSMatthew G. Knepley PetscCall(PetscRandomSetInterval(rnd, 0, 1.)); 9046c5a79ebSMatthew G. Knepley PetscCall(PetscRandomSetFromOptions(rnd)); 9056c5a79ebSMatthew G. Knepley 90635b38c60SMatthew G. Knepley for (p = 0; p < Np; ++p) { 90735b38c60SMatthew G. Knepley PetscInt s = species[p], d; 90835b38c60SMatthew G. Knepley PetscReal a[3], vel[3]; 90935b38c60SMatthew G. Knepley 9109566063dSJacob Faibussowitsch for (d = 0; d < dim; ++d) PetscCall(PetscRandomGetValueReal(rnd, &a[d])); 9119566063dSJacob Faibussowitsch PetscCall(sampler(a, NULL, vel)); 912ad540459SPierre Jolivet for (d = 0; d < dim; ++d) v[p * dim + d] = (v0[s] / v0[0]) * vel[d]; 91335b38c60SMatthew G. Knepley } 9146c5a79ebSMatthew G. Knepley PetscCall(PetscRandomDestroy(&rnd)); 9156c5a79ebSMatthew G. Knepley } 9169566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **)&v)); 9179566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "species", NULL, NULL, (void **)&species)); 9183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 91935b38c60SMatthew G. Knepley } 92035b38c60SMatthew G. Knepley 92135b38c60SMatthew G. Knepley /*@ 92235b38c60SMatthew G. Knepley DMSwarmInitializeVelocitiesFromOptions - Set the initial velocities of particles using a distribution determined from options. 92335b38c60SMatthew G. Knepley 92420f4b53cSBarry Smith Collective 92535b38c60SMatthew G. Knepley 92635b38c60SMatthew G. Knepley Input Parameters: 92720f4b53cSBarry Smith + sw - The `DMSWARM` object 92835b38c60SMatthew G. Knepley - v0 - The velocity scale for nondimensionalization for each species 92935b38c60SMatthew G. Knepley 93035b38c60SMatthew G. Knepley Level: advanced 93135b38c60SMatthew G. Knepley 93220f4b53cSBarry Smith .seealso: `DMSWARM`, `DMSwarmComputeLocalSize()`, `DMSwarmInitializeCoordinates()`, `DMSwarmInitializeVelocities()` 93335b38c60SMatthew G. Knepley @*/ 934d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmInitializeVelocitiesFromOptions(DM sw, const PetscReal v0[]) 935d71ae5a4SJacob Faibussowitsch { 93635b38c60SMatthew G. Knepley PetscProbFunc sampler; 93735b38c60SMatthew G. Knepley PetscInt dim; 93835b38c60SMatthew G. Knepley const char *prefix; 9396c5a79ebSMatthew G. Knepley char funcname[PETSC_MAX_PATH_LEN]; 9406c5a79ebSMatthew G. Knepley PetscBool flg; 94135b38c60SMatthew G. Knepley 94235b38c60SMatthew G. Knepley PetscFunctionBegin; 943d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)sw), "", "DMSwarm Options", "DMSWARM"); 9446c5a79ebSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_swarm_velocity_function", "Function to determine particle velocities", "DMSwarmSetVelocityFunction", funcname, funcname, sizeof(funcname), &flg)); 945d0609cedSBarry Smith PetscOptionsEnd(); 9466c5a79ebSMatthew G. Knepley if (flg) { 9478434afd1SBarry Smith PetscSimplePointFn *velFunc; 9486c5a79ebSMatthew G. Knepley 9496c5a79ebSMatthew G. Knepley PetscCall(PetscDLSym(NULL, funcname, (void **)&velFunc)); 9506c5a79ebSMatthew G. Knepley PetscCheck(velFunc, PetscObjectComm((PetscObject)sw), PETSC_ERR_ARG_WRONG, "Could not locate function %s", funcname); 9516c5a79ebSMatthew G. Knepley PetscCall(DMSwarmSetVelocityFunction(sw, velFunc)); 9526c5a79ebSMatthew G. Knepley } 9539566063dSJacob Faibussowitsch PetscCall(DMGetDimension(sw, &dim)); 9549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sw, &prefix)); 9559566063dSJacob Faibussowitsch PetscCall(PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_velocity_density", NULL, NULL, &sampler)); 9569566063dSJacob Faibussowitsch PetscCall(DMSwarmInitializeVelocities(sw, sampler, v0)); 9573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 95835b38c60SMatthew G. Knepley } 959