xref: /petsc/src/dm/impls/swarm/swarmpic.c (revision ea3d72757116e45d91c18dcbec367aa5cd88a124)
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>
694f7d2dcSDave May #include "data_bucket.h"
70e2ec84fSDave May 
80e2ec84fSDave May /*
90e2ec84fSDave May  Error chceking macto to ensure the swarm type is correct and that a cell DM has been set
100e2ec84fSDave May */
110e2ec84fSDave May #define DMSWARMPICVALID(dm) \
120e2ec84fSDave May { \
130e2ec84fSDave May   DM_Swarm *_swarm = (DM_Swarm*)(dm)->data; \
140e2ec84fSDave May   if (_swarm->swarm_type != DMSWARM_PIC) SETERRQ(PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Only valid for DMSwarm-PIC. You must call DMSwarmSetType(dm,DMSWARM_PIC)"); \
150e2ec84fSDave May   else \
160e2ec84fSDave May     if (!_swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)(dm)),PETSC_ERR_SUP,"Only valid for DMSwarmPIC if the cell DM is set. You must call DMSwarmSetCellDM(dm,celldm)"); \
170e2ec84fSDave May }
180e2ec84fSDave May 
190e2ec84fSDave May /* Coordinate insertition/addition API */
200e2ec84fSDave May /*@C
210e2ec84fSDave May    DMSwarmSetPointsUniformCoordinates - Set point coordinates in a DMSwarm on a regular (ijk) grid
220e2ec84fSDave May 
230e2ec84fSDave May    Collective on DM
240e2ec84fSDave May 
250e2ec84fSDave May    Input parameters:
260e2ec84fSDave May +  dm - the DMSwarm
270e2ec84fSDave May .  min - minimum coordinate values in the x, y, z directions (array of length dim)
280e2ec84fSDave May .  max - maximum coordinate values in the x, y, z directions (array of length dim)
290e2ec84fSDave May .  npoints - number of points in each spatial direction (array of length dim)
300e2ec84fSDave May -  mode - indicates whether to append points to the swarm (ADD_VALUES), or over-ride existing points (INSERT_VALUES)
310e2ec84fSDave May 
320e2ec84fSDave May    Level: beginner
330e2ec84fSDave May 
340e2ec84fSDave May    Notes:
350e2ec84fSDave May    When using mode = INSERT_VALUES, this method will reset the number of particles in the DMSwarm
360e2ec84fSDave May    to be npoints[0]*npoints[1] (2D) or npoints[0]*npoints[1]*npoints[2] (3D). When using mode = ADD_VALUES,
370e2ec84fSDave May    new points will be appended to any already existing in the DMSwarm
380e2ec84fSDave May 
390e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
400e2ec84fSDave May @*/
410e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointsUniformCoordinates(DM dm,PetscReal min[],PetscReal max[],PetscInt npoints[],InsertMode mode)
420e2ec84fSDave May {
430e2ec84fSDave May   PetscErrorCode ierr;
440e2ec84fSDave May   PetscReal gmin[] = {PETSC_MAX_REAL ,PETSC_MAX_REAL, PETSC_MAX_REAL};
450e2ec84fSDave May   PetscReal gmax[] = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
460e2ec84fSDave May   PetscInt i,j,k,N,bs,b,n_estimate,n_curr,n_new_est,p,n_found;
470e2ec84fSDave May   Vec coorlocal;
480e2ec84fSDave May   const PetscScalar *_coor;
490e2ec84fSDave May   DM celldm;
500e2ec84fSDave May   PetscReal dx[3];
512e3d3761SDave May   PetscInt _npoints[] = { 0, 0, 1 };
520e2ec84fSDave May   Vec pos;
530e2ec84fSDave May   PetscScalar *_pos;
540e2ec84fSDave May   PetscReal *swarm_coor;
550e2ec84fSDave May   PetscInt *swarm_cellid;
560e2ec84fSDave May   PetscSF sfcell = NULL;
570e2ec84fSDave May   const PetscSFNode *LA_sfcell;
580e2ec84fSDave May 
590e2ec84fSDave May   PetscFunctionBegin;
600e2ec84fSDave May   DMSWARMPICVALID(dm);
610e2ec84fSDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
620e2ec84fSDave May   ierr = DMGetCoordinatesLocal(celldm,&coorlocal);CHKERRQ(ierr);
630e2ec84fSDave May   ierr = VecGetSize(coorlocal,&N);CHKERRQ(ierr);
640e2ec84fSDave May   ierr = VecGetBlockSize(coorlocal,&bs);CHKERRQ(ierr);
650e2ec84fSDave May   N = N / bs;
660e2ec84fSDave May   ierr = VecGetArrayRead(coorlocal,&_coor);CHKERRQ(ierr);
670e2ec84fSDave May   for (i=0; i<N; i++) {
680e2ec84fSDave May     for (b=0; b<bs; b++) {
69a5f152d1SDave May       gmin[b] = PetscMin(gmin[b],PetscRealPart(_coor[bs*i+b]));
70a5f152d1SDave May       gmax[b] = PetscMax(gmax[b],PetscRealPart(_coor[bs*i+b]));
710e2ec84fSDave May     }
720e2ec84fSDave May   }
730e2ec84fSDave May   ierr = VecRestoreArrayRead(coorlocal,&_coor);CHKERRQ(ierr);
740e2ec84fSDave May 
750e2ec84fSDave May   for (b=0; b<bs; b++) {
7671844bb8SDave May     if (npoints[b] > 1) {
770e2ec84fSDave May       dx[b] = (max[b] - min[b])/((PetscReal)(npoints[b]-1));
7871844bb8SDave May     } else {
7971844bb8SDave May       dx[b] = 0.0;
8071844bb8SDave May     }
812e3d3761SDave May 
822e3d3761SDave May     _npoints[b] = npoints[b];
830e2ec84fSDave May   }
840e2ec84fSDave May 
850e2ec84fSDave May   /* determine number of points living in the bounding box */
860e2ec84fSDave May   n_estimate = 0;
872e3d3761SDave May   for (k=0; k<_npoints[2]; k++) {
882e3d3761SDave May     for (j=0; j<_npoints[1]; j++) {
892e3d3761SDave May       for (i=0; i<_npoints[0]; i++) {
900e2ec84fSDave May         PetscReal xp[] = {0.0,0.0,0.0};
910e2ec84fSDave May         PetscInt ijk[3];
920e2ec84fSDave May         PetscBool point_inside = PETSC_TRUE;
930e2ec84fSDave May 
940e2ec84fSDave May         ijk[0] = i;
950e2ec84fSDave May         ijk[1] = j;
960e2ec84fSDave May         ijk[2] = k;
970e2ec84fSDave May         for (b=0; b<bs; b++) {
980e2ec84fSDave May           xp[b] = min[b] + ijk[b] * dx[b];
990e2ec84fSDave May         }
1000e2ec84fSDave May         for (b=0; b<bs; b++) {
1010e2ec84fSDave May           if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; }
1020e2ec84fSDave May           if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; }
1030e2ec84fSDave May         }
1040e2ec84fSDave May         if (point_inside) { n_estimate++; }
1050e2ec84fSDave May       }
1060e2ec84fSDave May     }
1070e2ec84fSDave May   }
1080e2ec84fSDave May 
1090e2ec84fSDave May   /* create candidate list */
110c28a3c15SDave May   ierr = VecCreate(PETSC_COMM_SELF,&pos);CHKERRQ(ierr);
1110e2ec84fSDave May   ierr = VecSetSizes(pos,bs*n_estimate,PETSC_DECIDE);CHKERRQ(ierr);
1120e2ec84fSDave May   ierr = VecSetBlockSize(pos,bs);CHKERRQ(ierr);
1130e2ec84fSDave May   ierr = VecSetFromOptions(pos);CHKERRQ(ierr);
1140e2ec84fSDave May   ierr = VecGetArray(pos,&_pos);CHKERRQ(ierr);
1150e2ec84fSDave May 
1160e2ec84fSDave May   n_estimate = 0;
1172e3d3761SDave May   for (k=0; k<_npoints[2]; k++) {
1182e3d3761SDave May     for (j=0; j<_npoints[1]; j++) {
1192e3d3761SDave May       for (i=0; i<_npoints[0]; i++) {
1200e2ec84fSDave May         PetscReal xp[] = {0.0,0.0,0.0};
1210e2ec84fSDave May         PetscInt ijk[3];
1220e2ec84fSDave May         PetscBool point_inside = PETSC_TRUE;
1230e2ec84fSDave May 
1240e2ec84fSDave May         ijk[0] = i;
1250e2ec84fSDave May         ijk[1] = j;
1260e2ec84fSDave May         ijk[2] = k;
1270e2ec84fSDave May         for (b=0; b<bs; b++) {
1280e2ec84fSDave May           xp[b] = min[b] + ijk[b] * dx[b];
1290e2ec84fSDave May         }
1300e2ec84fSDave May         for (b=0; b<bs; b++) {
1310e2ec84fSDave May           if (xp[b] < gmin[b]) { point_inside = PETSC_FALSE; }
1320e2ec84fSDave May           if (xp[b] > gmax[b]) { point_inside = PETSC_FALSE; }
1330e2ec84fSDave May         }
1340e2ec84fSDave May         if (point_inside) {
1350e2ec84fSDave May           for (b=0; b<bs; b++) {
1360e2ec84fSDave May             _pos[bs*n_estimate+b] = xp[b];
1370e2ec84fSDave May           }
1380e2ec84fSDave May           n_estimate++;
1390e2ec84fSDave May         }
1400e2ec84fSDave May       }
1410e2ec84fSDave May     }
1420e2ec84fSDave May   }
1430e2ec84fSDave May   ierr = VecRestoreArray(pos,&_pos);CHKERRQ(ierr);
1440e2ec84fSDave May 
1450e2ec84fSDave May   /* locate points */
1460e2ec84fSDave May   ierr = DMLocatePoints(celldm,pos,DM_POINTLOCATION_NONE,&sfcell);CHKERRQ(ierr);
1470e2ec84fSDave May 
1480e2ec84fSDave May   ierr = PetscSFGetGraph(sfcell, NULL, NULL, NULL, &LA_sfcell);CHKERRQ(ierr);
1490e2ec84fSDave May   n_found = 0;
1500e2ec84fSDave May   for (p=0; p<n_estimate; p++) {
1510e2ec84fSDave May     if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) {
1520e2ec84fSDave May       n_found++;
1530e2ec84fSDave May     }
1540e2ec84fSDave May   }
1550e2ec84fSDave May 
1560e2ec84fSDave May   /* adjust size */
1570e2ec84fSDave May   if (mode == ADD_VALUES) {
1580e2ec84fSDave May     ierr = DMSwarmGetLocalSize(dm,&n_curr);CHKERRQ(ierr);
1590e2ec84fSDave May     n_new_est = n_curr + n_found;
1600e2ec84fSDave May     ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr);
1610e2ec84fSDave May   }
1620e2ec84fSDave May   if (mode == INSERT_VALUES) {
1630e2ec84fSDave May     n_curr = 0;
1640e2ec84fSDave May     n_new_est = n_found;
1650e2ec84fSDave May     ierr = DMSwarmSetLocalSizes(dm,n_new_est,-1);CHKERRQ(ierr);
1660e2ec84fSDave May   }
1670e2ec84fSDave May 
1680e2ec84fSDave May   /* initialize new coords, cell owners, pid */
1690e2ec84fSDave May   ierr = VecGetArrayRead(pos,&_coor);CHKERRQ(ierr);
1700e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
1710e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
1720e2ec84fSDave May   n_found = 0;
1730e2ec84fSDave May   for (p=0; p<n_estimate; p++) {
1740e2ec84fSDave May     if (LA_sfcell[p].index != DMLOCATEPOINT_POINT_NOT_FOUND) {
1750e2ec84fSDave May       for (b=0; b<bs; b++) {
1760ca99263SDave May         swarm_coor[bs*(n_curr + n_found) + b] = PetscRealPart(_coor[bs*p+b]);
1770e2ec84fSDave May       }
1780e2ec84fSDave May       swarm_cellid[n_curr + n_found] = LA_sfcell[p].index;
1790e2ec84fSDave May       n_found++;
1800e2ec84fSDave May     }
1810e2ec84fSDave May   }
1820e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
1830e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
1840e2ec84fSDave May   ierr = VecRestoreArrayRead(pos,&_coor);CHKERRQ(ierr);
1850e2ec84fSDave May 
1860e2ec84fSDave May   ierr = PetscSFDestroy(&sfcell);CHKERRQ(ierr);
1870e2ec84fSDave May   ierr = VecDestroy(&pos);CHKERRQ(ierr);
1880e2ec84fSDave May 
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 
1950e2ec84fSDave May    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);
2360e2ec84fSDave May   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(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;
2550e2ec84fSDave May     ierr = MPI_Bcast(&my_npoints,1,MPIU_INT,0,comm);CHKERRQ(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     }
2620e2ec84fSDave May     ierr = MPI_Bcast(my_coor,bs*my_npoints,MPIU_REAL,0,comm);CHKERRQ(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 
3530e2ec84fSDave May   PetscFunctionReturn(0);
3540e2ec84fSDave May }
3550e2ec84fSDave May 
3560e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM,DM,DMSwarmPICLayoutType,PetscInt);
3570e2ec84fSDave May extern PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM,DM,DMSwarmPICLayoutType,PetscInt);
3580e2ec84fSDave May 
3590e2ec84fSDave May /*@C
3600e2ec84fSDave May    DMSwarmInsertPointsUsingCellDM - Insert point coordinates within each cell
3610e2ec84fSDave May 
3620e2ec84fSDave May    Not collective
3630e2ec84fSDave May 
3640e2ec84fSDave May    Input parameters:
3650e2ec84fSDave May +  dm - the DMSwarm
3660e2ec84fSDave May .  layout_type - method used to fill each cell with the cell DM
3670e2ec84fSDave May -  fill_param - parameter controlling how many points per cell are added (the meaning of this parameter is dependent on the layout type)
3680e2ec84fSDave May 
3690e2ec84fSDave May  Level: beginner
3700e2ec84fSDave May 
3710e2ec84fSDave May  Notes:
372*ea3d7275SDave May  * The insert method will reset any previous defined points within the DMSwarm.
373*ea3d7275SDave May  * When using a DMDA both 2D and 3D are supported for all layout types provided you are using DMDA_ELEMENT_Q1.
374*ea3d7275SDave May  * When using a DMPLEX the following case are supported
375*ea3d7275SDave May  (i)   DMSWARMPIC_LAYOUT_REGULAR: 2D (triangle),
376*ea3d7275SDave May  (ii)  DMSWARMPIC_LAYOUT_GAUSS: 2D and 3D provided the cell is a tri/tet or a quad/hex,
377*ea3d7275SDave May  (iii) DMSWARMPIC_LAYOUT_SUBDIVISION: 2D and 3D for quad/hex and 2D tri.
3780e2ec84fSDave May 
3790e2ec84fSDave May .seealso: DMSwarmPICLayoutType, DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
3800e2ec84fSDave May @*/
3810e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmInsertPointsUsingCellDM(DM dm,DMSwarmPICLayoutType layout_type,PetscInt fill_param)
3820e2ec84fSDave May {
3830e2ec84fSDave May   PetscErrorCode ierr;
3840e2ec84fSDave May   DM celldm;
3850e2ec84fSDave May   PetscBool isDA,isPLEX;
3860e2ec84fSDave May 
3870e2ec84fSDave May   PetscFunctionBegin;
3880e2ec84fSDave May   DMSWARMPICVALID(dm);
3890e2ec84fSDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
3900e2ec84fSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr);
3910e2ec84fSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr);
3920e2ec84fSDave May   if (isDA) {
3930e2ec84fSDave May     ierr = private_DMSwarmInsertPointsUsingCellDM_DA(dm,celldm,layout_type,fill_param);CHKERRQ(ierr);
3940e2ec84fSDave May   } else if (isPLEX) {
3950e2ec84fSDave May     ierr = private_DMSwarmInsertPointsUsingCellDM_PLEX(dm,celldm,layout_type,fill_param);CHKERRQ(ierr);
3960e2ec84fSDave May   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX");
3970e2ec84fSDave May 
3980e2ec84fSDave May   PetscFunctionReturn(0);
3990e2ec84fSDave May }
4000e2ec84fSDave May 
401431382f2SDave 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.
419*ea3d7275SDave May  Only supported for DMPLEX. If you are using a DMDA it is recommended to either use
420*ea3d7275SDave May  DMSwarmInsertPointsUsingCellDM(), or extract and set the coordinates yourself using
421*ea3d7275SDave May  PetscReal *coor;
422*ea3d7275SDave May  DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor);
423*ea3d7275SDave May  // user code to define the coordinates here
424*ea3d7275SDave May  DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&coor);
425431382f2SDave May 
426431382f2SDave May .seealso: DMSwarmSetCellDM(), DMSwarmInsertPointsUsingCellDM()
427431382f2SDave May @*/
428431382f2SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetPointCoordinatesCellwise(DM dm,PetscInt npoints,PetscReal xi[])
4290e2ec84fSDave May {
430431382f2SDave May   PetscErrorCode ierr;
431431382f2SDave May   DM celldm;
432431382f2SDave May   PetscBool isDA,isPLEX;
433431382f2SDave May 
4340e2ec84fSDave May   PetscFunctionBegin;
435431382f2SDave May   DMSWARMPICVALID(dm);
436431382f2SDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
437431382f2SDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr);
438431382f2SDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr);
439431382f2SDave May   if (isDA) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMPLEX. Recommended you use DMSwarmInsertPointsUsingCellDM()");
440431382f2SDave May   else if (isPLEX) {
441431382f2SDave May     ierr = private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,xi);CHKERRQ(ierr);
442431382f2SDave May   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX");
443431382f2SDave May 
4440e2ec84fSDave May   PetscFunctionReturn(0);
4450e2ec84fSDave May }
446431382f2SDave May 
4470e2ec84fSDave May 
4480e2ec84fSDave May /* Field projection API */
44994f7d2dcSDave May extern PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]);
45094f7d2dcSDave May extern PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[]);
45194f7d2dcSDave May 
45294f7d2dcSDave May /*@C
45394f7d2dcSDave May    DMSwarmProjectFields - Project a set of swarm fields onto the cell DM
45494f7d2dcSDave May 
45594f7d2dcSDave May    Collective on Vec
45694f7d2dcSDave May 
45794f7d2dcSDave May    Input parameters:
45894f7d2dcSDave May +  dm - the DMSwarm
45994f7d2dcSDave May .  nfields - the number of swarm fields to project
46094f7d2dcSDave May .  fieldnames - the textual names of the swarm fields to project
46194f7d2dcSDave May .  fields - an array of Vec's of length nfields
46294f7d2dcSDave May -  reuse - flag indicating whether the array and contents of fields should be re-used or internally allocated
46394f7d2dcSDave May 
46494f7d2dcSDave May    Currently, the only available projection method consists of
46594f7d2dcSDave May      phi_i = \sum_{p=0}^{np} N_i(x_p) phi_p dJ / \sum_{p=0}^{np} N_i(x_p) dJ
46694f7d2dcSDave May    where phi_p is the swarm field at point p,
46794f7d2dcSDave May      N_i() is the cell DM basis function at vertex i,
46894f7d2dcSDave May      dJ is the determinant of the cell Jacobian and
46994f7d2dcSDave May      phi_i is the projected vertex value of the field phi.
47094f7d2dcSDave May 
47194f7d2dcSDave May    Level: beginner
47294f7d2dcSDave May 
47394f7d2dcSDave May    Notes:
47494f7d2dcSDave 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.
47694f7d2dcSDave May    - Only swarm fields registered with data type = PETSC_REAL can be projected onto the cell DM.
47794f7d2dcSDave May    - Only swarm fields of block size = 1 can currently be projected.
47894f7d2dcSDave May    - The only projection methods currently only support the DA (2D) and PLEX (triangles 2D).
47994f7d2dcSDave May 
48094f7d2dcSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
48194f7d2dcSDave May @*/
48294f7d2dcSDave May PETSC_EXTERN PetscErrorCode DMSwarmProjectFields(DM dm,PetscInt nfields,const char *fieldnames[],Vec **fields,PetscBool reuse)
4830e2ec84fSDave May {
48494f7d2dcSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
48594f7d2dcSDave May   DataField *gfield;
48694f7d2dcSDave May   DM celldm;
48794f7d2dcSDave May   PetscBool isDA,isPLEX;
48894f7d2dcSDave May   Vec *vecs;
48994f7d2dcSDave May   PetscInt f,nvecs;
49094f7d2dcSDave May   PetscInt project_type = 0;
49194f7d2dcSDave May   PetscErrorCode ierr;
49294f7d2dcSDave May 
4930e2ec84fSDave May   PetscFunctionBegin;
49494f7d2dcSDave May   DMSWARMPICVALID(dm);
49594f7d2dcSDave May   ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
49694f7d2dcSDave May   ierr = PetscMalloc1(nfields,&gfield);CHKERRQ(ierr);
49794f7d2dcSDave May   nvecs = 0;
49894f7d2dcSDave May   for (f=0; f<nfields; f++) {
49994f7d2dcSDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldnames[f],&gfield[f]);CHKERRQ(ierr);
50094f7d2dcSDave May     if (gfield[f]->petsc_type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields using a data type = PETSC_REAL");
50194f7d2dcSDave May     if (gfield[f]->bs != 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Projection only valid for fields with block size = 1");
50294f7d2dcSDave May     nvecs += gfield[f]->bs;
50394f7d2dcSDave May   }
50494f7d2dcSDave May   if (!reuse) {
50594f7d2dcSDave May     ierr = PetscMalloc1(nvecs,&vecs);CHKERRQ(ierr);
50694f7d2dcSDave May     for (f=0; f<nvecs; f++) {
50794f7d2dcSDave May       ierr = DMCreateGlobalVector(celldm,&vecs[f]);CHKERRQ(ierr);
50894f7d2dcSDave May       ierr = PetscObjectSetName((PetscObject)vecs[f],gfield[f]->name);CHKERRQ(ierr);
50994f7d2dcSDave May     }
51094f7d2dcSDave May   } else {
51194f7d2dcSDave May     vecs = *fields;
51294f7d2dcSDave May   }
51394f7d2dcSDave May 
51494f7d2dcSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isDA);CHKERRQ(ierr);
51594f7d2dcSDave May   ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isPLEX);CHKERRQ(ierr);
51694f7d2dcSDave May   if (isDA) {
51794f7d2dcSDave May     ierr = private_DMSwarmProjectFields_DA(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr);
51894f7d2dcSDave May   } else if (isPLEX) {
51994f7d2dcSDave May     ierr = private_DMSwarmProjectFields_PLEX(dm,celldm,project_type,nfields,gfield,vecs);CHKERRQ(ierr);
52094f7d2dcSDave May   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only supported for cell DMs of type DMDA and DMPLEX");
52194f7d2dcSDave May 
52294f7d2dcSDave May   ierr = PetscFree(gfield);CHKERRQ(ierr);
52394f7d2dcSDave May   if (!reuse) {
52494f7d2dcSDave May     *fields = vecs;
52594f7d2dcSDave May   }
52694f7d2dcSDave May 
5270e2ec84fSDave May   PetscFunctionReturn(0);
5280e2ec84fSDave May }
5290e2ec84fSDave May 
5300e2ec84fSDave May /*@C
531b799feefSDave May    DMSwarmCreatePointPerCellCount - Count the number of points within all cells in the cell DM
5320e2ec84fSDave May 
5330e2ec84fSDave May    Not collective
5340e2ec84fSDave May 
5350e2ec84fSDave May    Input parameter:
5360e2ec84fSDave May .  dm - the DMSwarm
5370e2ec84fSDave May 
5380e2ec84fSDave May    Output parameters:
5390e2ec84fSDave May +  ncells - the number of cells in the cell DM (optional argument, pass NULL to ignore)
540b799feefSDave May -  count - array of length ncells containing the number of points per cell
5410e2ec84fSDave May 
5420e2ec84fSDave May    Level: beginner
5430e2ec84fSDave May 
5440e2ec84fSDave May    Notes:
5450e2ec84fSDave May    The array count is allocated internally and must be free'd by the user.
5460e2ec84fSDave May 
5470e2ec84fSDave May .seealso: DMSwarmSetType(), DMSwarmSetCellDM(), DMSwarmType
5480e2ec84fSDave May @*/
5490e2ec84fSDave May PETSC_EXTERN PetscErrorCode DMSwarmCreatePointPerCellCount(DM dm,PetscInt *ncells,PetscInt **count)
5500e2ec84fSDave May {
551b799feefSDave May   PetscErrorCode ierr;
552b799feefSDave May   PetscBool      isvalid;
553b799feefSDave May   PetscInt       nel;
554b799feefSDave May   PetscInt       *sum;
555b799feefSDave May 
5560e2ec84fSDave May   PetscFunctionBegin;
557b799feefSDave May   ierr = DMSwarmSortGetIsValid(dm,&isvalid);CHKERRQ(ierr);
558b799feefSDave May   nel = 0;
559b799feefSDave May   if (isvalid) {
560b799feefSDave May     PetscInt e;
561b799feefSDave May 
562b799feefSDave May     ierr = DMSwarmSortGetSizes(dm,&nel,NULL);CHKERRQ(ierr);
563b799feefSDave May 
564b799feefSDave May     ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr);
565b799feefSDave May     for (e=0; e<nel; e++) {
566b799feefSDave May       ierr = DMSwarmSortGetNumberOfPointsPerCell(dm,e,&sum[e]);CHKERRQ(ierr);
567b799feefSDave May     }
568b799feefSDave May   } else {
569b799feefSDave May     DM        celldm;
570b799feefSDave May     PetscBool isda,isplex,isshell;
571b799feefSDave May     PetscInt  p,npoints;
572b799feefSDave May     PetscInt *swarm_cellid;
573b799feefSDave May 
574b799feefSDave May     /* get the number of cells */
575b799feefSDave May     ierr = DMSwarmGetCellDM(dm,&celldm);CHKERRQ(ierr);
576b799feefSDave May     ierr = PetscObjectTypeCompare((PetscObject)celldm,DMDA,&isda);CHKERRQ(ierr);
577b799feefSDave May     ierr = PetscObjectTypeCompare((PetscObject)celldm,DMPLEX,&isplex);CHKERRQ(ierr);
578b799feefSDave May     ierr = PetscObjectTypeCompare((PetscObject)celldm,DMSHELL,&isshell);CHKERRQ(ierr);
579b799feefSDave May     if (isda) {
580b799feefSDave May       PetscInt _nel,_npe;
581b799feefSDave May       const PetscInt *_element;
582b799feefSDave May 
583b799feefSDave May       ierr = DMDAGetElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr);
584b799feefSDave May       nel = _nel;
585b799feefSDave May       ierr = DMDARestoreElements(celldm,&_nel,&_npe,&_element);CHKERRQ(ierr);
586b799feefSDave May     } else if (isplex) {
587b799feefSDave May       PetscInt ps,pe;
588b799feefSDave May 
589b799feefSDave May       ierr = DMPlexGetHeightStratum(celldm,0,&ps,&pe);CHKERRQ(ierr);
590b799feefSDave May       nel = pe - ps;
591b799feefSDave May     } else if (isshell) {
592b799feefSDave May       PetscErrorCode (*method_DMShellGetNumberOfCells)(DM,PetscInt*);
593b799feefSDave May 
594b799feefSDave May       ierr = PetscObjectQueryFunction((PetscObject)celldm,"DMGetNumberOfCells_C",&method_DMShellGetNumberOfCells);CHKERRQ(ierr);
595b799feefSDave May       if (method_DMShellGetNumberOfCells) {
596b799feefSDave May         ierr = method_DMShellGetNumberOfCells(celldm,&nel);CHKERRQ(ierr);
597b799feefSDave 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 );");
598b799feefSDave 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");
599b799feefSDave May 
600b799feefSDave May     ierr = PetscMalloc1(nel,&sum);CHKERRQ(ierr);
601b799feefSDave May     ierr = PetscMemzero(sum,sizeof(PetscInt)*nel);CHKERRQ(ierr);
602b799feefSDave May     ierr = DMSwarmGetLocalSize(dm,&npoints);CHKERRQ(ierr);
603b799feefSDave May     ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
604b799feefSDave May     for (p=0; p<npoints; p++) {
605b799feefSDave May       if (swarm_cellid[p] != DMLOCATEPOINT_POINT_NOT_FOUND) {
606b799feefSDave May         sum[ swarm_cellid[p] ]++;
607b799feefSDave May       }
608b799feefSDave May     }
609b799feefSDave May     ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
610b799feefSDave May   }
611b799feefSDave May   if (ncells) { *ncells = nel; }
612b799feefSDave May   *count  = sum;
6130e2ec84fSDave May   PetscFunctionReturn(0);
6140e2ec84fSDave May }
615