xref: /petsc/src/dm/impls/swarm/swarmpic.c (revision 35b38c60984a921feffd14a898962025aec18fc1)
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>
6*35b38c60SMatthew G. Knepley #include <petscdt.h>
7279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
80e2ec84fSDave May 
9*35b38c60SMatthew G. Knepley #include <petsc/private/petscfeimpl.h> /* For CoordinatesRefToReal() */
10*35b38c60SMatthew G. Knepley 
110e2ec84fSDave May /*
125627991aSBarry Smith  Error checking to ensure the swarm type is correct and that a cell DM has been set
130e2ec84fSDave May */
140e2ec84fSDave May #define DMSWARMPICVALID(dm) \
150e2ec84fSDave May { \
160e2ec84fSDave May   DM_Swarm *_swarm = (DM_Swarm*)(dm)->data; \
172c71b3e2SJacob Faibussowitsch   PetscCheckFalse(_swarm->swarm_type != DMSWARM_PIC,PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Valid only for DMSwarm-PIC. You must call DMSwarmSetType(dm,DMSWARM_PIC)"); \
180e2ec84fSDave May   else \
192c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!_swarm->dmcell,PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Valid only for DMSwarmPIC if the cell DM is set. You must call DMSwarmSetCellDM(dm,celldm)"); \
200e2ec84fSDave May }
210e2ec84fSDave May 
220e2ec84fSDave May /* Coordinate insertition/addition API */
230e2ec84fSDave May /*@C
240e2ec84fSDave May    DMSwarmSetPointsUniformCoordinates - Set point coordinates in a DMSwarm on a regular (ijk) grid
250e2ec84fSDave May 
26d083f849SBarry Smith    Collective on dm
270e2ec84fSDave May 
280e2ec84fSDave May    Input parameters:
290e2ec84fSDave May +  dm - the DMSwarm
300e2ec84fSDave May .  min - minimum coordinate values in the x, y, z directions (array of length dim)
310e2ec84fSDave May .  max - maximum coordinate values in the x, y, z directions (array of length dim)
320e2ec84fSDave May .  npoints - number of points in each spatial direction (array of length dim)
330e2ec84fSDave May -  mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES)
340e2ec84fSDave May 
350e2ec84fSDave May    Level: beginner
360e2ec84fSDave May 
370e2ec84fSDave May    Notes:
380e2ec84fSDave May    When using mode = INSERT_VALUES, this method will reset the number of particles in the DMSwarm
390e2ec84fSDave May    to be npoints[0]*npoints[1] (2D) or npoints[0]*npoints[1]*npoints[2] (3D). When using mode = ADD_VALUES,
400e2ec84fSDave May    new points will be appended to any already existing in the DMSwarm
410e2ec84fSDave May 
420e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
430e2ec84fSDave May @*/
440e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm,PetscReal min[],PetscReal max[],PetscInt npoints[],InsertMode mode)
450e2ec84fSDave May {
460e2ec84fSDave May   PetscErrorCode    ierr;
470e2ec84fSDave May   PetscReal         gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL};
480e2ec84fSDave May   PetscReal         gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
490e2ec84fSDave May   PetscInt          i,j,k,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found;
500e2ec84fSDave May   Vec               coorlocal;
510e2ec84fSDave May   const PetscScalar *_coor;
520e2ec84fSDave May   DM                celldm;
530e2ec84fSDave May   PetscReal         dx[3];
542e3d3761SDave May   PetscInt          _npoints[] = { 0, 0, 1 };
550e2ec84fSDave May   Vec               pos;
560e2ec84fSDave May   PetscScalar       *_pos;
570e2ec84fSDave May   PetscReal         *swarm_coor;
580e2ec84fSDave May   PetscInt          *swarm_cellid;
590e2ec84fSDave May   PetscSF           sfcell = NULL;
600e2ec84fSDave May   const PetscSFNode *LA_sfcell;
610e2ec84fSDave May 
620e2ec84fSDave May   PetscFunctionBegin;
630e2ec84fSDave May   DMSWARMPICVALID(dm);
640e2ec84fSDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
650e2ec84fSDave May   ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr);
660e2ec84fSDave May   ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr);
670e2ec84fSDave May   ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr);
680e2ec84fSDave May   N = N / bs;
690e2ec84fSDave May   ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr);
700e2ec84fSDave May   for (i=0; i<N; i++) {
710e2ec84fSDave May     for (b=0; b<bs; b++) {
72a5f152d1SDave May       gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b]));
73a5f152d1SDave May       gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b]));
740e2ec84fSDave May     }
750e2ec84fSDave May   }
760e2ec84fSDave May   ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr);
770e2ec84fSDave May 
780e2ec84fSDave May   for (b=0; b<bs; b++) {
7971844bb8SDave May     if (npoints[b] > 1) {
800e2ec84fSDave May       dx[b] = (max[b] - min[b])/((PetscReal)(npoints[b]-1));
8171844bb8SDave May     } else {
8271844bb8SDave May       dx[b] = 0.0;
8371844bb8SDave May     }
842e3d3761SDave May     _npoints[b] = npoints[b];
850e2ec84fSDave May   }
860e2ec84fSDave May 
870e2ec84fSDave May   /* determine number of points living in the bounding box */
880e2ec84fSDave May   n_estimate = 0;
892e3d3761SDave May   for (k=0; k<_npoints[2]; k++) {
902e3d3761SDave May     for (j=0; j<_npoints[1]; j++) {
912e3d3761SDave May       for (i=0; i<_npoints[0]; i++) {
920e2ec84fSDave May         PetscReal xp[] = {0.0,0.0,0.0};
930e2ec84fSDave May         PetscInt ijk[3];
940e2ec84fSDave May         PetscBool point_inside = PETSC_TRUE;
950e2ec84fSDave May 
960e2ec84fSDave May         ijk[0] = i;
970e2ec84fSDave May         ijk[1] = j;
980e2ec84fSDave May         ijk[2] = k;
990e2ec84fSDave May         for (b=0; b<bs; b++) {
1000e2ec84fSDave May           xp[b] = min[b] + ijk[b] * dx[b];
1010e2ec84fSDave May         }
1020e2ec84fSDave May         for (b=0; b<bs; b++) {
1030e2ec84fSDave May           if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; }
1040e2ec84fSDave May           if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; }
1050e2ec84fSDave May         }
1060e2ec84fSDave May         if (point_inside) { n_estimate++; }
1070e2ec84fSDave May       }
1080e2ec84fSDave May     }
1090e2ec84fSDave May   }
1100e2ec84fSDave May 
1110e2ec84fSDave May   /* create candidate list */
112c28a3c15SDave May   ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr);
1130e2ec84fSDave May   ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr);
1140e2ec84fSDave May   ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr);
1150e2ec84fSDave May   ierr = VecSetFromOptions(pos);CHKERRQ(ierr);
1160e2ec84fSDave May   ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr);
1170e2ec84fSDave May 
1180e2ec84fSDave May   n_estimate = 0;
1192e3d3761SDave May   for (k=0; k<_npoints[2]; k++) {
1202e3d3761SDave May     for (j=0; j<_npoints[1]; j++) {
1212e3d3761SDave May       for (i=0; i<_npoints[0]; i++) {
1220e2ec84fSDave May         PetscReal xp[] = {0.0,0.0,0.0};
1230e2ec84fSDave May         PetscInt  ijk[3];
1240e2ec84fSDave May         PetscBool point_inside = PETSC_TRUE;
1250e2ec84fSDave May 
1260e2ec84fSDave May         ijk[0] = i;
1270e2ec84fSDave May         ijk[1] = j;
1280e2ec84fSDave May         ijk[2] = k;
1290e2ec84fSDave May         for (b=0; b<bs; b++) {
1300e2ec84fSDave May           xp[b] = min[b] + ijk[b] * dx[b];
1310e2ec84fSDave May         }
1320e2ec84fSDave May         for (b=0; b<bs; b++) {
1330e2ec84fSDave May           if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; }
1340e2ec84fSDave May           if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; }
1350e2ec84fSDave May         }
1360e2ec84fSDave May         if (point_inside) {
1370e2ec84fSDave May           for (b=0; b<bs; b++) {
1380e2ec84fSDave May             _pos[bs*n_estimate+b] = xp[b];
1390e2ec84fSDave May           }
1400e2ec84fSDave May           n_estimate++;
1410e2ec84fSDave May         }
1420e2ec84fSDave May       }
1430e2ec84fSDave May     }
1440e2ec84fSDave May   }
1450e2ec84fSDave May   ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr);
1460e2ec84fSDave May 
1470e2ec84fSDave May   /* locate points */
1480e2ec84fSDave May   ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr);
1490e2ec84fSDave May   ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr);
1500e2ec84fSDave May   n_found = 0;
1510e2ec84fSDave May   for (p=0; p<n_estimate; p++) {
1520e2ec84fSDave May     if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) {
1530e2ec84fSDave May       n_found++;
1540e2ec84fSDave May     }
1550e2ec84fSDave May   }
1560e2ec84fSDave May 
1570e2ec84fSDave May   /* adjust size */
1580e2ec84fSDave May   if (mode == ADD_VALUES) {
1590e2ec84fSDave May     ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr);
1600e2ec84fSDave May     n_new_est = n_curr + n_found;
1610e2ec84fSDave May     ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr);
1620e2ec84fSDave May   }
1630e2ec84fSDave May   if (mode == INSERT_VALUES) {
1640e2ec84fSDave May     n_curr = 0;
1650e2ec84fSDave May     n_new_est = n_found;
1660e2ec84fSDave May     ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr);
1670e2ec84fSDave May   }
1680e2ec84fSDave May 
1690e2ec84fSDave May   /* initialize new coords, cell owners, pid */
1700e2ec84fSDave May   ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr);
1710e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
1720e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
1730e2ec84fSDave May   n_found = 0;
1740e2ec84fSDave May   for (p=0; p<n_estimate; p++) {
1750e2ec84fSDave May     if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) {
1760e2ec84fSDave May       for (b=0; b<bs; b++) {
1770ca99263SDave May         swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]);
1780e2ec84fSDave May       }
1790e2ec84fSDave May       swarm_cellid[n_curr + n_found] = LA_sfcell[p].index;
1800e2ec84fSDave May       n_found++;
1810e2ec84fSDave May     }
1820e2ec84fSDave May   }
1830e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
1840e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
1850e2ec84fSDave May   ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr);
1860e2ec84fSDave May 
1870e2ec84fSDave May   ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr);
1880e2ec84fSDave May   ierr = VecDestroy(&pos);CHKERRQ(ierr);
1890e2ec84fSDave May   PetscFunctionReturn(0);
1900e2ec84fSDave May }
1910e2ec84fSDave May 
1920e2ec84fSDave May /*@C
1930e2ec84fSDave May    DMSwarmSetPointCoordinates - Set point coordinates in a DMSwarm from a user defined list
1940e2ec84fSDave May 
195d083f849SBarry Smith    Collective on dm
1960e2ec84fSDave May 
1970e2ec84fSDave May    Input parameters:
1980e2ec84fSDave May +  dm - the DMSwarm
1990e2ec84fSDave May .  npoints - the number of points to insert
2000e2ec84fSDave May .  coor - the coordinate values
2010e2ec84fSDave May .  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
2020e2ec84fSDave May -  mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES)
2030e2ec84fSDave May 
2040e2ec84fSDave May    Level: beginner
2050e2ec84fSDave May 
2060e2ec84fSDave May    Notes:
2070e2ec84fSDave May    If the user has specified redundant = PETSC_FALSE, the cell DM will attempt to locate the coordinates provided by coor[] within
2080e2ec84fSDave May    its sub-domain. If they any values within coor[] are not located in the sub-domain, they will be ignored and will not get
2090e2ec84fSDave May    added to the DMSwarm.
2100e2ec84fSDave May 
2110e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType, DMSwarmSetPointsUniformCoordinates()
2120e2ec84fSDave May @*/
2130e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinates(DM dm,PetscInt npoints,PetscReal coor[],PetscBool redundant,InsertMode mode)
2140e2ec84fSDave May {
2150e2ec84fSDave May   PetscErrorCode    ierr;
2160e2ec84fSDave May   PetscReal         gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL};
2170e2ec84fSDave May   PetscReal         gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
2180e2ec84fSDave May   PetscInt          i,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found;
2190e2ec84fSDave May   Vec               coorlocal;
2200e2ec84fSDave May   const PetscScalar *_coor;
2210e2ec84fSDave May   DM                celldm;
2220e2ec84fSDave May   Vec               pos;
2230e2ec84fSDave May   PetscScalar       *_pos;
2240e2ec84fSDave May   PetscReal         *swarm_coor;
2250e2ec84fSDave May   PetscInt          *swarm_cellid;
2260e2ec84fSDave May   PetscSF           sfcell = NULL;
2270e2ec84fSDave May   const PetscSFNode *LA_sfcell;
2280e2ec84fSDave May   PetscReal         *my_coor;
2290e2ec84fSDave May   PetscInt          my_npoints;
2300e2ec84fSDave May   PetscMPIInt       rank;
2310e2ec84fSDave May   MPI_Comm          comm;
2320e2ec84fSDave May 
2330e2ec84fSDave May   PetscFunctionBegin;
2340e2ec84fSDave May   DMSWARMPICVALID(dm);
2350e2ec84fSDave May   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
236ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
2370e2ec84fSDave May 
2380e2ec84fSDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
2390e2ec84fSDave May   ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr);
2400e2ec84fSDave May   ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr);
2410e2ec84fSDave May   ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr);
2420e2ec84fSDave May   N = N / bs;
2430e2ec84fSDave May   ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr);
2440e2ec84fSDave May   for (i=0; i<N; i++) {
2450e2ec84fSDave May     for (b=0; b<bs; b++) {
246a5f152d1SDave May       gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b]));
247a5f152d1SDave May       gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b]));
2480e2ec84fSDave May     }
2490e2ec84fSDave May   }
2500e2ec84fSDave May   ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr);
2510e2ec84fSDave May 
2520e2ec84fSDave May   /* broadcast points from rank 0 if requested */
2530e2ec84fSDave May   if (redundant) {
2540e2ec84fSDave May     my_npoints = npoints;
255ffc4695bSBarry Smith     ierr = MPI_Bcast(&my_npoints,1,MPIU_INT,0,comm);CHKERRMPI(ierr);
2560e2ec84fSDave May 
2570e2ec84fSDave May     if (rank > 0) { /* allocate space */
25871844bb8SDave May       ierr = PetscMalloc1(bs*my_npoints,&my_coor);CHKERRQ(ierr);
2590e2ec84fSDave May     } else {
2600e2ec84fSDave May       my_coor = coor;
2610e2ec84fSDave May     }
262ffc4695bSBarry Smith     ierr = MPI_Bcast(my_coor,bs*my_npoints,MPIU_REAL,0,comm);CHKERRMPI(ierr);
2630e2ec84fSDave May   } else {
2640e2ec84fSDave May     my_npoints = npoints;
2650e2ec84fSDave May     my_coor = coor;
2660e2ec84fSDave May   }
2670e2ec84fSDave May 
2680e2ec84fSDave May   /* determine the number of points living in the bounding box */
2690e2ec84fSDave May   n_estimate = 0;
2700e2ec84fSDave May   for (i=0; i<my_npoints; i++) {
2710e2ec84fSDave May     PetscBool point_inside = PETSC_TRUE;
2720e2ec84fSDave May 
2730e2ec84fSDave May     for (b=0; b<bs; b++) {
2740e2ec84fSDave May       if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; }
2750e2ec84fSDave May       if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; }
2760e2ec84fSDave May     }
2770e2ec84fSDave May     if (point_inside) { n_estimate++; }
2780e2ec84fSDave May   }
2790e2ec84fSDave May 
2800e2ec84fSDave May   /* create candidate list */
281c28a3c15SDave May   ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr);
2820e2ec84fSDave May   ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr);
2830e2ec84fSDave May   ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr);
2840e2ec84fSDave May   ierr = VecSetFromOptions(pos);CHKERRQ(ierr);
2850e2ec84fSDave May   ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr);
2860e2ec84fSDave May 
2870e2ec84fSDave May   n_estimate = 0;
2880e2ec84fSDave May   for (i=0; i<my_npoints; i++) {
2890e2ec84fSDave May     PetscBool point_inside = PETSC_TRUE;
2900e2ec84fSDave May 
2910e2ec84fSDave May     for (b=0; b<bs; b++) {
2920e2ec84fSDave May       if (my_coor[bs*i+b] < gmin[b]) { point_inside = PETSC_FALSE; }
2930e2ec84fSDave May       if (my_coor[bs*i+b] > gmax[b]) { point_inside = PETSC_FALSE; }
2940e2ec84fSDave May     }
2950e2ec84fSDave May     if (point_inside) {
2960e2ec84fSDave May       for (b=0; b<bs; b++) {
2970e2ec84fSDave May         _pos[bs*n_estimate+b] = my_coor[bs*i+b];
2980e2ec84fSDave May       }
2990e2ec84fSDave May       n_estimate++;
3000e2ec84fSDave May     }
3010e2ec84fSDave May   }
3020e2ec84fSDave May   ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr);
3030e2ec84fSDave May 
3040e2ec84fSDave May   /* locate points */
3050e2ec84fSDave May   ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr);
3060e2ec84fSDave May 
3070e2ec84fSDave May   ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr);
3080e2ec84fSDave May   n_found = 0;
3090e2ec84fSDave May   for (p=0; p<n_estimate; p++) {
3100e2ec84fSDave May     if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) {
3110e2ec84fSDave May       n_found++;
3120e2ec84fSDave May     }
3130e2ec84fSDave May   }
3140e2ec84fSDave May 
3150e2ec84fSDave May   /* adjust size */
3160e2ec84fSDave May   if (mode == ADD_VALUES) {
3170e2ec84fSDave May     ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr);
3180e2ec84fSDave May     n_new_est = n_curr + n_found;
3190e2ec84fSDave May     ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr);
3200e2ec84fSDave May   }
3210e2ec84fSDave May   if (mode == INSERT_VALUES) {
3220e2ec84fSDave May     n_curr = 0;
3230e2ec84fSDave May     n_new_est = n_found;
3240e2ec84fSDave May     ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr);
3250e2ec84fSDave May   }
3260e2ec84fSDave May 
3270e2ec84fSDave May   /* initialize new coords, cell owners, pid */
3280e2ec84fSDave May   ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr);
3290e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
3300e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
3310e2ec84fSDave May   n_found = 0;
3320e2ec84fSDave May   for (p=0; p<n_estimate; p++) {
3330e2ec84fSDave May     if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) {
3340e2ec84fSDave May       for (b=0; b<bs; b++) {
3350ca99263SDave May         swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]);
3360e2ec84fSDave May       }
3370e2ec84fSDave May       swarm_cellid[n_curr + n_found] = LA_sfcell[p].index;
3380e2ec84fSDave May       n_found++;
3390e2ec84fSDave May     }
3400e2ec84fSDave May   }
3410e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
3420e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
3430e2ec84fSDave May   ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr);
3440e2ec84fSDave May 
3450e2ec84fSDave May   if (redundant) {
3460e2ec84fSDave May     if (rank > 0) {
3470e2ec84fSDave May       ierr = PetscFree(my_coor);CHKERRQ(ierr);
3480e2ec84fSDave May     }
3490e2ec84fSDave May   }
3500e2ec84fSDave May   ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr);
3510e2ec84fSDave May   ierr = VecDestroy(&pos);CHKERRQ(ierr);
3520e2ec84fSDave May   PetscFunctionReturn(0);
3530e2ec84fSDave May }
3540e2ec84fSDave May 
3550e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM,DM,DMSwarmPICLayoutType,PetscInt);
3560e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM,DM,DMSwarmPICLayoutType,PetscInt);
3570e2ec84fSDave May 
3580e2ec84fSDave May /*@C
3590e2ec84fSDave May    DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell
3600e2ec84fSDave May 
3610e2ec84fSDave May    Not collective
3620e2ec84fSDave May 
3630e2ec84fSDave May    Input parameters:
3640e2ec84fSDave May +  dm - the DMSwarm
3650e2ec84fSDave May .  layout_type - method used to fill each cell with the cell DM
3660e2ec84fSDave May -  fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type)
3670e2ec84fSDave May 
3680e2ec84fSDave May    Level: beginner
3690e2ec84fSDave May 
3700e2ec84fSDave May    Notes:
371e7af74c8SDave May 
372e7af74c8SDave May    The insert method will reset any previous defined points within the DMSwarm.
373e7af74c8SDave May 
374e7af74c8SDave May    When using a DMDA both 2D and 3D are supported for all layout types provided you are using DMDA_ELEMENT_Q1.
375e7af74c8SDave May 
376e7af74c8SDave May    When using a DMPLEX the following case are supported:
377ea3d7275SDave May    (i) DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle),
378ea3d7275SDave May    (ii) DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex,
379ea3d7275SDave May    (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri.
3800e2ec84fSDave May 
3810e2ec84fSDave May .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
3820e2ec84fSDave May @*/
3830e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param)
3840e2ec84fSDave May {
3850e2ec84fSDave May   PetscErrorCode ierr;
3860e2ec84fSDave May   DM             celldm;
3870e2ec84fSDave May   PetscBool      isDA,isPLEX;
3880e2ec84fSDave May 
3890e2ec84fSDave May   PetscFunctionBegin;
3900e2ec84fSDave May   DMSWARMPICVALID(dm);
3910e2ec84fSDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
3920e2ec84fSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr);
3930e2ec84fSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr);
3940e2ec84fSDave May   if (isDA) {
3950e2ec84fSDave May     ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr);
3960e2ec84fSDave May   } else if (isPLEX) {
3970e2ec84fSDave May     ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr);
3980e2ec84fSDave May   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX");
3990e2ec84fSDave May   PetscFunctionReturn(0);
4000e2ec84fSDave May }
4010e2ec84fSDave May 
402431382f2SDave May extern PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM,DM,PetscInt,PetscReal*);
403431382f2SDave May 
404431382f2SDave May /*@C
405431382f2SDave May    DMSwarmSetPointCoordinatesCellwise - Insert point coordinates (defined over the reference cell) within each cell
406431382f2SDave May 
407431382f2SDave May    Not collective
408431382f2SDave May 
409431382f2SDave May    Input parameters:
410431382f2SDave May +  dm - the DMSwarm
411431382f2SDave May .  celldm - the cell DM
412431382f2SDave May .  npoints - the number of points to insert in each cell
413431382f2SDave May -  xi - the coordinates (defined in the local coordinate system for each cell) to insert
414431382f2SDave May 
415431382f2SDave May  Level: beginner
416431382f2SDave May 
417431382f2SDave May  Notes:
418431382f2SDave May  The method will reset any previous defined points within the DMSwarm.
419ea3d7275SDave May  Only supported for DMPLEX. If you are using a DMDA it is recommended to either use
420e7af74c8SDave May  DMSwarmInsertPointsUsingCellDM(), or extract and set the coordinates yourself the following code
421e7af74c8SDave May 
422e7af74c8SDave May $    PetscReal *coor;
423e7af74c8SDave May $    DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor);
424e7af74c8SDave May $    // user code to define the coordinates here
425e7af74c8SDave May $    DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor);
426431382f2SDave May 
427431382f2SDave May .seealso: DMSwarmSetCellDM(), DMSwarmInsertPointsUsingCellDM()
428431382f2SDave May @*/
429431382f2SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm,PetscInt npoints,PetscReal xi[])
4300e2ec84fSDave May {
431431382f2SDave May   PetscErrorCode ierr;
432431382f2SDave May   DM             celldm;
433431382f2SDave May   PetscBool      isDA,isPLEX;
434431382f2SDave May 
4350e2ec84fSDave May   PetscFunctionBegin;
436431382f2SDave May   DMSWARMPICVALID(dm);
437431382f2SDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
438431382f2SDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr);
439431382f2SDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr);
4402c71b3e2SJacob Faibussowitsch   PetscCheckFalse(isDA,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()");
441431382f2SDave May   else if (isPLEX) {
442431382f2SDave May     ierr = private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,xi);CHKERRQ(ierr);
443431382f2SDave May   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX");
4440e2ec84fSDave May   PetscFunctionReturn(0);
4450e2ec84fSDave May }
446431382f2SDave May 
4470e2ec84fSDave May /* Field projection API */
44877048351SPatrick Sanan extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DMSwarmDataField dfield[],Vec vecs[]);
44977048351SPatrick Sanan extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DMSwarmDataField dfield[],Vec vecs[]);
45094f7d2dcSDave May 
45194f7d2dcSDave May /*@C
45294f7d2dcSDave May    DMSwarmProjectFields - Project a set of swarm fields onto the cell DM
45394f7d2dcSDave May 
454d083f849SBarry Smith    Collective on dm
45594f7d2dcSDave May 
45694f7d2dcSDave May    Input parameters:
45794f7d2dcSDave May +  dm - the DMSwarm
45894f7d2dcSDave May .  nfields - the number of swarm fields to project
45994f7d2dcSDave May .  fieldnames - the textual names of the swarm fields to project
46094f7d2dcSDave May .  fields - an array of Vec's of length nfields
46194f7d2dcSDave May -  reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated
46294f7d2dcSDave May 
46394f7d2dcSDave May    Currently, the only available projection method consists of
46494f7d2dcSDave May      phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ
46594f7d2dcSDave May    where phi_p is the swarm field at point p,
46694f7d2dcSDave May      N_i() is the cell DM basis function at vertex i,
46794f7d2dcSDave May      dJ is the determinant of the cell Jacobian and
46894f7d2dcSDave May      phi_i is the projected vertex value of the field phi.
46994f7d2dcSDave May 
47094f7d2dcSDave May    Level: beginner
47194f7d2dcSDave May 
47294f7d2dcSDave May    Notes:
473e7af74c8SDave May 
474e7af74c8SDave May    If reuse = PETSC_FALSE, this function will allocate the array of Vec's, and each individual Vec.
47594f7d2dcSDave May      The user is responsible for destroying both the array and the individual Vec objects.
476e7af74c8SDave May 
477e7af74c8SDave May    Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM.
478e7af74c8SDave May 
479e7af74c8SDave May    Only swarm fields of block size = 1 can currently be projected.
480e7af74c8SDave May 
481e7af74c8SDave May    The only projection methods currently only support the DA (2D) and PLEX (triangles 2D).
48294f7d2dcSDave May 
48394f7d2dcSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
48494f7d2dcSDave May @*/
48594f7d2dcSDave May PETSC_EXTERN PetscErrorCode DMSwarmProjectFields(DM dm,PetscInt nfields,const char *fieldnames[],Vec **fields,PetscBool reuse)
4860e2ec84fSDave May {
48794f7d2dcSDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
48877048351SPatrick Sanan   DMSwarmDataField *gfield;
48994f7d2dcSDave May   DM               celldm;
49094f7d2dcSDave May   PetscBool        isDA,isPLEX;
49194f7d2dcSDave May   Vec              *vecs;
49294f7d2dcSDave May   PetscInt         f,nvecs;
49394f7d2dcSDave May   PetscInt         project_type = 0;
49494f7d2dcSDave May   PetscErrorCode   ierr;
49594f7d2dcSDave May 
4960e2ec84fSDave May   PetscFunctionBegin;
49794f7d2dcSDave May   DMSWARMPICVALID(dm);
49894f7d2dcSDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
49994f7d2dcSDave May   ierr = PetscMalloc1(nfields,&gfield);CHKERRQ(ierr);
50094f7d2dcSDave May   nvecs = 0;
50194f7d2dcSDave May   for (f=0; f<nfields; f++) {
50277048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldnames[f],&gfield[f]);CHKERRQ(ierr);
5032c71b3e2SJacob Faibussowitsch     PetscCheckFalse(gfield[f]->petsc_type != PETSC_REAL,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields using a data type = PETSC_REAL");
5042c71b3e2SJacob Faibussowitsch     PetscCheckFalse(gfield[f]->bs != 1,PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields with block size = 1");
50594f7d2dcSDave May     nvecs += gfield[f]->bs;
50694f7d2dcSDave May   }
50794f7d2dcSDave May   if (!reuse) {
50894f7d2dcSDave May     ierr = PetscMalloc1(nvecs,&vecs);CHKERRQ(ierr);
50994f7d2dcSDave May     for (f=0; f<nvecs; f++) {
51094f7d2dcSDave May       ierr = DMCreateGlobalVector(celldm,&vecs[f]);CHKERRQ(ierr);
51194f7d2dcSDave May       ierr = PetscObjectSetName((PetscObject)vecs[f],gfield[f]->name);CHKERRQ(ierr);
51294f7d2dcSDave May     }
51394f7d2dcSDave May   } else {
51494f7d2dcSDave May     vecs = *fields;
51594f7d2dcSDave May   }
51694f7d2dcSDave May 
51794f7d2dcSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr);
51894f7d2dcSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr);
51994f7d2dcSDave May   if (isDA) {
52094f7d2dcSDave May     ierr = private_DMSwarmProjectFields_DA(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr);
52194f7d2dcSDave May   } else if (isPLEX) {
52294f7d2dcSDave May     ierr = private_DMSwarmProjectFields_PLEX(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr);
52394f7d2dcSDave May   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX");
52494f7d2dcSDave May 
52594f7d2dcSDave May   ierr = PetscFree(gfield);CHKERRQ(ierr);
52694f7d2dcSDave May   if (!reuse) {
52794f7d2dcSDave May     *fields = vecs;
52894f7d2dcSDave May   }
5290e2ec84fSDave May   PetscFunctionReturn(0);
5300e2ec84fSDave May }
5310e2ec84fSDave May 
5320e2ec84fSDave May /*@C
533b799feefSDave May    DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM
5340e2ec84fSDave May 
5350e2ec84fSDave May    Not collective
5360e2ec84fSDave May 
5370e2ec84fSDave May    Input parameter:
5380e2ec84fSDave May .  dm - the DMSwarm
5390e2ec84fSDave May 
5400e2ec84fSDave May    Output parameters:
5410e2ec84fSDave May +  ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore)
542b799feefSDave May -  count - array of length ncells containing the number of points per cell
5430e2ec84fSDave May 
5440e2ec84fSDave May    Level: beginner
5450e2ec84fSDave May 
5460e2ec84fSDave May    Notes:
5470e2ec84fSDave May    The array count is allocated internally and must be free'd by the user.
5480e2ec84fSDave May 
5490e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
5500e2ec84fSDave May @*/
5510e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count)
5520e2ec84fSDave May {
553b799feefSDave May   PetscErrorCode ierr;
554b799feefSDave May   PetscBool      isvalid;
555b799feefSDave May   PetscInt       nel;
556b799feefSDave May   PetscInt       *sum;
557b799feefSDave May 
5580e2ec84fSDave May   PetscFunctionBegin;
559b799feefSDave May   ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr);
560b799feefSDave May   nel = 0;
561b799feefSDave May   if (isvalid) {
562b799feefSDave May     PetscInt e;
563b799feefSDave May 
564b799feefSDave May     ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr);
565b799feefSDave May 
566b799feefSDave May     ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr);
567b799feefSDave May     for (e=0; e<nel; e++) {
568b799feefSDave May       ierr = DMSwarmSortGetNumberOfPointsPerCell(dm,e,&sum[e]);CHKERRQ(ierr);
569b799feefSDave May     }
570b799feefSDave May   } else {
571b799feefSDave May     DM        celldm;
572b799feefSDave May     PetscBool isda,isplex,isshell;
573b799feefSDave May     PetscInt  p,npoints;
574b799feefSDave May     PetscInt *swarm_cellid;
575b799feefSDave May 
576b799feefSDave May     /* get the number of cells */
577b799feefSDave May     ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
578b799feefSDave May     ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isda);CHKERRQ(ierr);
579b799feefSDave May     ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isplex);CHKERRQ(ierr);
580b799feefSDave May     ierr = PetscObjectTypeCompare((PetscObject)celldm,DMSHELL,&isshell);CHKERRQ(ierr);
581b799feefSDave May     if (isda) {
582b799feefSDave May       PetscInt       _nel,_npe;
583b799feefSDave May       const PetscInt *_element;
584b799feefSDave May 
585b799feefSDave May       ierr = DMDAGetElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr);
586b799feefSDave May       nel = _nel;
587b799feefSDave May       ierr = DMDARestoreElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr);
588b799feefSDave May     } else if (isplex) {
589b799feefSDave May       PetscInt ps,pe;
590b799feefSDave May 
591b799feefSDave May       ierr = DMPlexGetHeightStratum(celldm,0,&ps,&pe);CHKERRQ(ierr);
592b799feefSDave May       nel = pe - ps;
593b799feefSDave May     } else if (isshell) {
594b799feefSDave May       PetscErrorCode (*method_DMShellGetNumberOfCells)(DM,PetscInt*);
595b799feefSDave May 
596b799feefSDave May       ierr = PetscObjectQueryFunction((PetscObject)celldm,"DMGetNumberOfCells_C",&method_DMShellGetNumberOfCells);CHKERRQ(ierr);
597b799feefSDave May       if (method_DMShellGetNumberOfCells) {
598b799feefSDave May         ierr = method_DMShellGetNumberOfCells(celldm,&nel);CHKERRQ(ierr);
599b799feefSDave May       } else 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);");
600b799feefSDave 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");
601b799feefSDave May 
602b799feefSDave May     ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr);
603580bdb30SBarry Smith     ierr = PetscArrayzero(sum,nel);CHKERRQ(ierr);
604b799feefSDave May     ierr = DMSwarmGetLocalSize(dm,&npoints);CHKERRQ(ierr);
605b799feefSDave May     ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
606b799feefSDave May     for (p=0; p<npoints; p++) {
607b799feefSDave May       if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) {
608b799feefSDave May         sum[ swarm_cellid[p] ]++;
609b799feefSDave May       }
610b799feefSDave May     }
611b799feefSDave May     ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
612b799feefSDave May   }
613b799feefSDave May   if (ncells) { *ncells = nel; }
614b799feefSDave May   *count  = sum;
6150e2ec84fSDave May   PetscFunctionReturn(0);
6160e2ec84fSDave May }
617*35b38c60SMatthew G. Knepley 
618*35b38c60SMatthew G. Knepley /*@
619*35b38c60SMatthew G. Knepley   DMSwarmGetNumSpecies - Get the number of particle species
620*35b38c60SMatthew G. Knepley 
621*35b38c60SMatthew G. Knepley   Not collective
622*35b38c60SMatthew G. Knepley 
623*35b38c60SMatthew G. Knepley   Input parameter:
624*35b38c60SMatthew G. Knepley . dm - the DMSwarm
625*35b38c60SMatthew G. Knepley 
626*35b38c60SMatthew G. Knepley   Output parameters:
627*35b38c60SMatthew G. Knepley . Ns - the number of species
628*35b38c60SMatthew G. Knepley 
629*35b38c60SMatthew G. Knepley   Level: intermediate
630*35b38c60SMatthew G. Knepley 
631*35b38c60SMatthew G. Knepley .seealso: DMSwarmSetNumSpecies(), DMSwarmSetType(), DMSwarmType
632*35b38c60SMatthew G. Knepley @*/
633*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmGetNumSpecies(DM sw, PetscInt *Ns)
634*35b38c60SMatthew G. Knepley {
635*35b38c60SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *) sw->data;
636*35b38c60SMatthew G. Knepley 
637*35b38c60SMatthew G. Knepley   PetscFunctionBegin;
638*35b38c60SMatthew G. Knepley   *Ns = swarm->Ns;
639*35b38c60SMatthew G. Knepley   PetscFunctionReturn(0);
640*35b38c60SMatthew G. Knepley }
641*35b38c60SMatthew G. Knepley 
642*35b38c60SMatthew G. Knepley /*@
643*35b38c60SMatthew G. Knepley   DMSwarmSetNumSpecies - Set the number of particle species
644*35b38c60SMatthew G. Knepley 
645*35b38c60SMatthew G. Knepley   Not collective
646*35b38c60SMatthew G. Knepley 
647*35b38c60SMatthew G. Knepley   Input parameter:
648*35b38c60SMatthew G. Knepley + dm - the DMSwarm
649*35b38c60SMatthew G. Knepley - Ns - the number of species
650*35b38c60SMatthew G. Knepley 
651*35b38c60SMatthew G. Knepley   Level: intermediate
652*35b38c60SMatthew G. Knepley 
653*35b38c60SMatthew G. Knepley .seealso: DMSwarmGetNumSpecies(), DMSwarmSetType(), DMSwarmType
654*35b38c60SMatthew G. Knepley @*/
655*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmSetNumSpecies(DM sw, PetscInt Ns)
656*35b38c60SMatthew G. Knepley {
657*35b38c60SMatthew G. Knepley   DM_Swarm *swarm = (DM_Swarm *) sw->data;
658*35b38c60SMatthew G. Knepley 
659*35b38c60SMatthew G. Knepley   PetscFunctionBegin;
660*35b38c60SMatthew G. Knepley   swarm->Ns =  Ns;
661*35b38c60SMatthew G. Knepley   PetscFunctionReturn(0);
662*35b38c60SMatthew G. Knepley }
663*35b38c60SMatthew G. Knepley 
664*35b38c60SMatthew G. Knepley /*@C
665*35b38c60SMatthew G. Knepley   DMSwarmComputeLocalSize - Compute the local number and distribution of particles based upon a density function
666*35b38c60SMatthew G. Knepley 
667*35b38c60SMatthew G. Knepley   Not collective
668*35b38c60SMatthew G. Knepley 
669*35b38c60SMatthew G. Knepley   Input Parameters:
670*35b38c60SMatthew G. Knepley + sw      - The DMSwarm
671*35b38c60SMatthew G. Knepley . N       - The target number of particles
672*35b38c60SMatthew G. Knepley - density - The density field for the particle layout, normalized to unity
673*35b38c60SMatthew G. Knepley 
674*35b38c60SMatthew G. Knepley   Note: One particle will be created for each species.
675*35b38c60SMatthew G. Knepley 
676*35b38c60SMatthew G. Knepley   Level: advanced
677*35b38c60SMatthew G. Knepley 
678*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSizeFromOptions()
679*35b38c60SMatthew G. Knepley @*/
680*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmComputeLocalSize(DM sw, PetscInt N, PetscProbFunc density)
681*35b38c60SMatthew G. Knepley {
682*35b38c60SMatthew G. Knepley   DM               dm;
683*35b38c60SMatthew G. Knepley   PetscQuadrature  quad;
684*35b38c60SMatthew G. Knepley   const PetscReal *xq, *wq;
685*35b38c60SMatthew G. Knepley   PetscInt        *npc, *cellid;
686*35b38c60SMatthew G. Knepley   PetscReal        xi0[3], scale[1] = {.01};
687*35b38c60SMatthew G. Knepley   PetscInt         Ns, cStart, cEnd, c, dim, d, Nq, q, Np = 0, p;
688*35b38c60SMatthew G. Knepley   PetscBool        simplex;
689*35b38c60SMatthew G. Knepley   PetscErrorCode   ierr;
690*35b38c60SMatthew G. Knepley 
691*35b38c60SMatthew G. Knepley   PetscFunctionBegin;
692*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetNumSpecies(sw, &Ns);CHKERRQ(ierr);
693*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetCellDM(sw, &dm);CHKERRQ(ierr);
694*35b38c60SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
695*35b38c60SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
696*35b38c60SMatthew G. Knepley   ierr = DMPlexIsSimplex(dm, &simplex);CHKERRQ(ierr);
697*35b38c60SMatthew G. Knepley   if (simplex) {ierr = PetscDTStroudConicalQuadrature(dim, 1, 5, -1.0, 1.0, &quad);CHKERRQ(ierr);}
698*35b38c60SMatthew G. Knepley   else         {ierr = PetscDTGaussTensorQuadrature(dim, 1, 5, -1.0, 1.0, &quad);CHKERRQ(ierr);}
699*35b38c60SMatthew G. Knepley   ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, &xq, &wq);CHKERRQ(ierr);
700*35b38c60SMatthew G. Knepley   ierr = PetscMalloc1(cEnd-cStart, &npc);CHKERRQ(ierr);
701*35b38c60SMatthew G. Knepley   /* Integrate the density function to get the number of particles in each cell */
702*35b38c60SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
703*35b38c60SMatthew G. Knepley   for (c = 0; c < cEnd-cStart; ++c) {
704*35b38c60SMatthew G. Knepley     const PetscInt cell = c + cStart;
705*35b38c60SMatthew G. Knepley     PetscReal v0[3], J[9], invJ[9], detJ;
706*35b38c60SMatthew G. Knepley     PetscReal n_int = 0.;
707*35b38c60SMatthew G. Knepley 
708*35b38c60SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
709*35b38c60SMatthew G. Knepley     for (q = 0; q < Nq; ++q) {
710*35b38c60SMatthew G. Knepley       PetscReal xr[3], den[3];
711*35b38c60SMatthew G. Knepley 
712*35b38c60SMatthew G. Knepley       CoordinatesRefToReal(dim, dim, xi0, v0, J, &xq[q*dim], xr);
713*35b38c60SMatthew G. Knepley       ierr = density(xr, scale, den);CHKERRQ(ierr);
714*35b38c60SMatthew G. Knepley       n_int += N*den[0]*wq[q];
715*35b38c60SMatthew G. Knepley     }
716*35b38c60SMatthew G. Knepley     npc[c]  = (PetscInt) n_int;
717*35b38c60SMatthew G. Knepley     npc[c] *= Ns;
718*35b38c60SMatthew G. Knepley     Np     += npc[c];
719*35b38c60SMatthew G. Knepley   }
720*35b38c60SMatthew G. Knepley   ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr);
721*35b38c60SMatthew G. Knepley   ierr = DMSwarmSetLocalSizes(sw, Np, 0);CHKERRQ(ierr);
722*35b38c60SMatthew G. Knepley 
723*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid);CHKERRQ(ierr);
724*35b38c60SMatthew G. Knepley   for (c = 0, p = 0; c < cEnd-cStart; ++c) {
725*35b38c60SMatthew G. Knepley     for (q = 0; q < npc[c]; ++q, ++p) cellid[p] = c;
726*35b38c60SMatthew G. Knepley   }
727*35b38c60SMatthew G. Knepley   ierr = DMSwarmRestoreField(sw, DMSwarmPICField_cellid, NULL, NULL, (void **) &cellid);CHKERRQ(ierr);
728*35b38c60SMatthew G. Knepley   ierr = PetscFree(npc);CHKERRQ(ierr);
729*35b38c60SMatthew G. Knepley   PetscFunctionReturn(0);
730*35b38c60SMatthew G. Knepley }
731*35b38c60SMatthew G. Knepley 
732*35b38c60SMatthew G. Knepley /*@
733*35b38c60SMatthew G. Knepley   DMSwarmComputeLocalSizeFromOptions - Compute the local number and distribution of particles based upon a density function determined by options
734*35b38c60SMatthew G. Knepley 
735*35b38c60SMatthew G. Knepley   Not collective
736*35b38c60SMatthew G. Knepley 
737*35b38c60SMatthew G. Knepley   Input Parameters:
738*35b38c60SMatthew G. Knepley , sw - The DMSwarm
739*35b38c60SMatthew G. Knepley 
740*35b38c60SMatthew G. Knepley   Level: advanced
741*35b38c60SMatthew G. Knepley 
742*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize()
743*35b38c60SMatthew G. Knepley @*/
744*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmComputeLocalSizeFromOptions(DM sw)
745*35b38c60SMatthew G. Knepley {
746*35b38c60SMatthew G. Knepley   DTProbDensityType den = DTPROB_DENSITY_CONSTANT;
747*35b38c60SMatthew G. Knepley   PetscProbFunc     pdf;
748*35b38c60SMatthew G. Knepley   PetscInt          N, Ns, dim;
749*35b38c60SMatthew G. Knepley   PetscBool         flg;
750*35b38c60SMatthew G. Knepley   const char       *prefix;
751*35b38c60SMatthew G. Knepley   PetscErrorCode    ierr;
752*35b38c60SMatthew G. Knepley 
753*35b38c60SMatthew G. Knepley   PetscFunctionBegin;
754*35b38c60SMatthew G. Knepley   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject) sw), "", "DMSwarm Options", "DMSWARM");CHKERRQ(ierr);
755*35b38c60SMatthew G. Knepley   ierr = PetscOptionsInt("-dm_swarm_num_particles", "The target number of particles", "", N, &N, NULL);CHKERRQ(ierr);
756*35b38c60SMatthew G. Knepley   ierr = PetscOptionsInt("-dm_swarm_num_species", "The number of species", "DMSwarmSetNumSpecies", Ns, &Ns, &flg);CHKERRQ(ierr);
757*35b38c60SMatthew G. Knepley   if (flg) {ierr = DMSwarmSetNumSpecies(sw, Ns);CHKERRQ(ierr);}
758*35b38c60SMatthew G. Knepley   ierr = PetscOptionsEnum("-dm_swarm_density", "Method to compute particle density <constant, gaussian>", "", DTProbDensityTypes, (PetscEnum) den, (PetscEnum *) &den, NULL);CHKERRQ(ierr);
759*35b38c60SMatthew G. Knepley   ierr = PetscOptionsEnd();CHKERRQ(ierr);
760*35b38c60SMatthew G. Knepley 
761*35b38c60SMatthew G. Knepley   ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr);
762*35b38c60SMatthew G. Knepley   ierr = PetscObjectGetOptionsPrefix((PetscObject) sw, &prefix);CHKERRQ(ierr);
763*35b38c60SMatthew G. Knepley   ierr = PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_coordinate_density", &pdf, NULL, NULL);CHKERRQ(ierr);
764*35b38c60SMatthew G. Knepley   ierr = DMSwarmComputeLocalSize(sw, N, pdf);CHKERRQ(ierr);
765*35b38c60SMatthew G. Knepley   PetscFunctionReturn(0);
766*35b38c60SMatthew G. Knepley }
767*35b38c60SMatthew G. Knepley 
768*35b38c60SMatthew G. Knepley /*@
769*35b38c60SMatthew G. Knepley   DMSwarmInitializeCoordinates - Determine the initial coordinates of particles for a PIC method
770*35b38c60SMatthew G. Knepley 
771*35b38c60SMatthew G. Knepley   Not collective
772*35b38c60SMatthew G. Knepley 
773*35b38c60SMatthew G. Knepley   Input Parameters:
774*35b38c60SMatthew G. Knepley , sw - The DMSwarm
775*35b38c60SMatthew G. Knepley 
776*35b38c60SMatthew G. Knepley   Note: Currently, we randomly place particles in their assigned cell
777*35b38c60SMatthew G. Knepley 
778*35b38c60SMatthew G. Knepley   Level: advanced
779*35b38c60SMatthew G. Knepley 
780*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize(), DMSwarmInitializeVelocities()
781*35b38c60SMatthew G. Knepley @*/
782*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmInitializeCoordinates(DM sw)
783*35b38c60SMatthew G. Knepley {
784*35b38c60SMatthew G. Knepley   DM             dm;
785*35b38c60SMatthew G. Knepley   PetscRandom    rnd;
786*35b38c60SMatthew G. Knepley   PetscScalar   *weight;
787*35b38c60SMatthew G. Knepley   PetscReal     *x, xi0[3];
788*35b38c60SMatthew G. Knepley   PetscInt      *species;
789*35b38c60SMatthew G. Knepley   PetscBool      removePoints = PETSC_TRUE;
790*35b38c60SMatthew G. Knepley   PetscDataType  dtype;
791*35b38c60SMatthew G. Knepley   PetscInt       Ns, cStart, cEnd, c, dim, d, s, bs;
792*35b38c60SMatthew G. Knepley   PetscErrorCode ierr;
793*35b38c60SMatthew G. Knepley 
794*35b38c60SMatthew G. Knepley   PetscFunctionBeginUser;
795*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetNumSpecies(sw, &Ns);CHKERRQ(ierr);
796*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetCellDM(sw, &dm);CHKERRQ(ierr);
797*35b38c60SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
798*35b38c60SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
799*35b38c60SMatthew G. Knepley 
800*35b38c60SMatthew G. Knepley   /* Set particle position randomly in cell, set weights to 1 */
801*35b38c60SMatthew G. Knepley   ierr = PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rnd);CHKERRQ(ierr);
802*35b38c60SMatthew G. Knepley   ierr = PetscRandomSetInterval(rnd, -1.0, 1.0);CHKERRQ(ierr);
803*35b38c60SMatthew G. Knepley   ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr);
804*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetField(sw, "w_q", &bs, &dtype, (void **) &weight);CHKERRQ(ierr);
805*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void **) &x);CHKERRQ(ierr);
806*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetField(sw, "species", NULL, NULL, (void **) &species);
807*35b38c60SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr);
808*35b38c60SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
809*35b38c60SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
810*35b38c60SMatthew G. Knepley     PetscReal v0[3], J[9], invJ[9], detJ;
811*35b38c60SMatthew G. Knepley     PetscInt *pidx, Npc, q;
812*35b38c60SMatthew G. Knepley 
813*35b38c60SMatthew G. Knepley     ierr = DMSwarmSortGetPointsPerCell(sw, c, &Npc, &pidx);CHKERRQ(ierr);
814*35b38c60SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
815*35b38c60SMatthew G. Knepley     for (q = 0; q < Npc; ++q) {
816*35b38c60SMatthew G. Knepley       const PetscInt p = pidx[q];
817*35b38c60SMatthew G. Knepley       PetscReal      xref[3];
818*35b38c60SMatthew G. Knepley 
819*35b38c60SMatthew G. Knepley       for (d = 0; d < dim; ++d) {ierr = PetscRandomGetValueReal(rnd, &xref[d]);CHKERRQ(ierr);}
820*35b38c60SMatthew G. Knepley       CoordinatesRefToReal(dim, dim, xi0, v0, J, xref, &x[p*dim]);
821*35b38c60SMatthew G. Knepley 
822*35b38c60SMatthew G. Knepley       weight[p] = 1.0;
823*35b38c60SMatthew G. Knepley       for (s = 0; s < Ns; ++s) species[p] = p % Ns;
824*35b38c60SMatthew G. Knepley     }
825*35b38c60SMatthew G. Knepley     ierr = PetscFree(pidx);CHKERRQ(ierr);
826*35b38c60SMatthew G. Knepley   }
827*35b38c60SMatthew G. Knepley   ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr);
828*35b38c60SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr);
829*35b38c60SMatthew G. Knepley   ierr = DMSwarmRestoreField(sw, "w_q", NULL, NULL, (void **) &weight);CHKERRQ(ierr);
830*35b38c60SMatthew G. Knepley   ierr = DMSwarmRestoreField(sw, DMSwarmPICField_coor, NULL, NULL, (void **) &x);CHKERRQ(ierr);
831*35b38c60SMatthew G. Knepley   ierr = DMSwarmRestoreField(sw, "species", NULL, NULL, (void **) &species);CHKERRQ(ierr);
832*35b38c60SMatthew G. Knepley   ierr = DMSwarmMigrate(sw, removePoints);CHKERRQ(ierr);
833*35b38c60SMatthew G. Knepley   ierr = DMLocalizeCoordinates(sw);CHKERRQ(ierr);
834*35b38c60SMatthew G. Knepley   PetscFunctionReturn(0);
835*35b38c60SMatthew G. Knepley }
836*35b38c60SMatthew G. Knepley 
837*35b38c60SMatthew G. Knepley /*@C
838*35b38c60SMatthew G. Knepley   DMSwarmInitializeVelocities - Set the initial velocities of particles using a distribution.
839*35b38c60SMatthew G. Knepley 
840*35b38c60SMatthew G. Knepley   Collective on dm
841*35b38c60SMatthew G. Knepley 
842*35b38c60SMatthew G. Knepley   Input Parameters:
843*35b38c60SMatthew G. Knepley + sw      - The DMSwarm object
844*35b38c60SMatthew G. Knepley . sampler - A function which uniformly samples the velocity PDF
845*35b38c60SMatthew G. Knepley - v0      - The velocity scale for nondimensionalization for each species
846*35b38c60SMatthew G. Knepley 
847*35b38c60SMatthew G. Knepley   Level: advanced
848*35b38c60SMatthew G. Knepley 
849*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize(), DMSwarmInitializeCoordinates(), DMSwarmInitializeVelocitiesFromOptions()
850*35b38c60SMatthew G. Knepley @*/
851*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmInitializeVelocities(DM sw, PetscProbFunc sampler, const PetscReal v0[])
852*35b38c60SMatthew G. Knepley {
853*35b38c60SMatthew G. Knepley   PetscRandom    rnd;
854*35b38c60SMatthew G. Knepley   PetscReal     *v;
855*35b38c60SMatthew G. Knepley   PetscInt      *species;
856*35b38c60SMatthew G. Knepley   PetscInt       dim, Np, p;
857*35b38c60SMatthew G. Knepley   PetscErrorCode ierr;
858*35b38c60SMatthew G. Knepley 
859*35b38c60SMatthew G. Knepley   PetscFunctionBegin;
860*35b38c60SMatthew G. Knepley   ierr = PetscRandomCreate(PetscObjectComm((PetscObject) sw), &rnd);CHKERRQ(ierr);
861*35b38c60SMatthew G. Knepley   ierr = PetscRandomSetInterval(rnd, 0, 1.);CHKERRQ(ierr);
862*35b38c60SMatthew G. Knepley   ierr = PetscRandomSetFromOptions(rnd);CHKERRQ(ierr);
863*35b38c60SMatthew G. Knepley 
864*35b38c60SMatthew G. Knepley   ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr);
865*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(sw, &Np);CHKERRQ(ierr);
866*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetField(sw, "velocity", NULL, NULL, (void **) &v);CHKERRQ(ierr);
867*35b38c60SMatthew G. Knepley   ierr = DMSwarmGetField(sw, "species", NULL, NULL, (void **) &species);
868*35b38c60SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
869*35b38c60SMatthew G. Knepley     PetscInt  s = species[p], d;
870*35b38c60SMatthew G. Knepley     PetscReal a[3], vel[3];
871*35b38c60SMatthew G. Knepley 
872*35b38c60SMatthew G. Knepley     for (d = 0; d < dim; ++d) {ierr = PetscRandomGetValueReal(rnd, &a[d]);CHKERRQ(ierr);}
873*35b38c60SMatthew G. Knepley     ierr = sampler(a, NULL, vel);CHKERRQ(ierr);
874*35b38c60SMatthew G. Knepley     for (d = 0; d < dim; ++d) {v[p*dim+d] = (v0[s] / v0[0]) * vel[d];}
875*35b38c60SMatthew G. Knepley   }
876*35b38c60SMatthew G. Knepley   ierr = DMSwarmRestoreField(sw, "velocity", NULL, NULL, (void **) &v);CHKERRQ(ierr);
877*35b38c60SMatthew G. Knepley   ierr = DMSwarmRestoreField(sw, "species", NULL, NULL, (void **) &species);CHKERRQ(ierr);
878*35b38c60SMatthew G. Knepley   ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr);
879*35b38c60SMatthew G. Knepley   PetscFunctionReturn(0);
880*35b38c60SMatthew G. Knepley }
881*35b38c60SMatthew G. Knepley 
882*35b38c60SMatthew G. Knepley /*@
883*35b38c60SMatthew G. Knepley   DMSwarmInitializeVelocitiesFromOptions - Set the initial velocities of particles using a distribution determined from options.
884*35b38c60SMatthew G. Knepley 
885*35b38c60SMatthew G. Knepley   Collective on dm
886*35b38c60SMatthew G. Knepley 
887*35b38c60SMatthew G. Knepley   Input Parameters:
888*35b38c60SMatthew G. Knepley + sw      - The DMSwarm object
889*35b38c60SMatthew G. Knepley - v0      - The velocity scale for nondimensionalization for each species
890*35b38c60SMatthew G. Knepley 
891*35b38c60SMatthew G. Knepley   Level: advanced
892*35b38c60SMatthew G. Knepley 
893*35b38c60SMatthew G. Knepley .seealso: DMSwarmComputeLocalSize(), DMSwarmInitializeCoordinates(), DMSwarmInitializeVelocities()
894*35b38c60SMatthew G. Knepley @*/
895*35b38c60SMatthew G. Knepley PetscErrorCode DMSwarmInitializeVelocitiesFromOptions(DM sw, const PetscReal v0[])
896*35b38c60SMatthew G. Knepley {
897*35b38c60SMatthew G. Knepley   PetscProbFunc  sampler;
898*35b38c60SMatthew G. Knepley   PetscInt       dim;
899*35b38c60SMatthew G. Knepley   const char    *prefix;
900*35b38c60SMatthew G. Knepley   PetscErrorCode ierr;
901*35b38c60SMatthew G. Knepley 
902*35b38c60SMatthew G. Knepley   PetscFunctionBegin;
903*35b38c60SMatthew G. Knepley   ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr);
904*35b38c60SMatthew G. Knepley   ierr = PetscObjectGetOptionsPrefix((PetscObject) sw, &prefix);CHKERRQ(ierr);
905*35b38c60SMatthew G. Knepley   ierr = PetscProbCreateFromOptions(dim, prefix, "-dm_swarm_velocity_density", NULL, NULL, &sampler);CHKERRQ(ierr);
906*35b38c60SMatthew G. Knepley   ierr = DMSwarmInitializeVelocities(sw, sampler, v0);CHKERRQ(ierr);
907*35b38c60SMatthew G. Knepley   PetscFunctionReturn(0);
908*35b38c60SMatthew G. Knepley }
909