xref: /petsc/src/dm/impls/swarm/swarmpic.c (revision 6497c311e7b976d467be1503c1effce92a60525c)
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