xref: /petsc/src/dm/impls/swarm/swarmpic_da.c (revision 1f52046ff98bf2fe5d2e903a453a49cf34422aa4)
10e2ec84fSDave May 
20e2ec84fSDave May #include <petsc.h>
30e2ec84fSDave May #include <petscdm.h>
40e2ec84fSDave May #include <petscdmda.h>
50e2ec84fSDave May #include <petscdmswarm.h>
6*1f52046fSDave May #include <petsc/private/dmswarmimpl.h>
7*1f52046fSDave May #include "data_bucket.h"
80e2ec84fSDave May 
90e2ec84fSDave May PetscErrorCode private_DMSwarmCreateCellLocalCoords_DA_Q1_Regular(PetscInt dim,PetscInt np[],PetscInt *_npoints,PetscReal **_xi)
100e2ec84fSDave May {
110e2ec84fSDave May   PetscErrorCode ierr;
120e2ec84fSDave May   PetscReal *xi;
130e2ec84fSDave May   PetscInt d,npoints,cnt;
140e2ec84fSDave May   PetscReal ds[] = {0.0,0.0,0.0};
150e2ec84fSDave May   PetscInt ii,jj,kk;
160e2ec84fSDave May 
170e2ec84fSDave May   PetscFunctionBegin;
180e2ec84fSDave May   switch (dim) {
190e2ec84fSDave May     case 1:
200e2ec84fSDave May       npoints = np[0];
210e2ec84fSDave May       break;
220e2ec84fSDave May     case 2:
230e2ec84fSDave May       npoints = np[0]*np[1];
240e2ec84fSDave May       break;
250e2ec84fSDave May     case 3:
260e2ec84fSDave May       npoints = np[0]*np[1]*np[2];
270e2ec84fSDave May       break;
280e2ec84fSDave May   }
290e2ec84fSDave May   for (d=0; d<dim; d++) {
300e2ec84fSDave May     ds[d] = 2.0 / ((PetscReal)np[d]);
310e2ec84fSDave May   }
320e2ec84fSDave May 
330e2ec84fSDave May   ierr = PetscMalloc1(dim*npoints,&xi);CHKERRQ(ierr);
340e2ec84fSDave May 
350e2ec84fSDave May   switch (dim) {
360e2ec84fSDave May     case 1:
370e2ec84fSDave May       cnt = 0;
380e2ec84fSDave May       for (ii=0; ii<np[0]; ii++) {
390e2ec84fSDave May         xi[dim*cnt+0] = -1.0 + 0.5*ds[d] + ii*ds[0];
400e2ec84fSDave May         cnt++;
410e2ec84fSDave May       }
420e2ec84fSDave May       break;
430e2ec84fSDave May 
440e2ec84fSDave May     case 2:
450e2ec84fSDave May       cnt = 0;
460e2ec84fSDave May       for (jj=0; jj<np[1]; jj++) {
470e2ec84fSDave May         for (ii=0; ii<np[0]; ii++) {
480e2ec84fSDave May           xi[dim*cnt+0] = -1.0 + 0.5*ds[0] + ii*ds[0];
490e2ec84fSDave May           xi[dim*cnt+1] = -1.0 + 0.5*ds[1] + jj*ds[1];
500e2ec84fSDave May           cnt++;
510e2ec84fSDave May         }
520e2ec84fSDave May       }
530e2ec84fSDave May       break;
540e2ec84fSDave May 
550e2ec84fSDave May     case 3:
560e2ec84fSDave May       cnt = 0;
570e2ec84fSDave May       for (kk=0; kk<np[2]; kk++) {
580e2ec84fSDave May         for (jj=0; jj<np[1]; jj++) {
590e2ec84fSDave May           for (ii=0; ii<np[0]; ii++) {
600e2ec84fSDave May             xi[dim*cnt+0] = -1.0 + 0.5*ds[0] + ii*ds[0];
610e2ec84fSDave May             xi[dim*cnt+1] = -1.0 + 0.5*ds[1] + jj*ds[1];
620e2ec84fSDave May             xi[dim*cnt+2] = -1.0 + 0.5*ds[2] + kk*ds[2];
630e2ec84fSDave May             cnt++;
640e2ec84fSDave May           }
650e2ec84fSDave May         }
660e2ec84fSDave May       }
670e2ec84fSDave May       break;
680e2ec84fSDave May   }
690e2ec84fSDave May 
700e2ec84fSDave May   *_npoints = npoints;
710e2ec84fSDave May   *_xi = xi;
720e2ec84fSDave May 
730e2ec84fSDave May   PetscFunctionReturn(0);
740e2ec84fSDave May }
750e2ec84fSDave May 
760e2ec84fSDave May PetscErrorCode private_DMSwarmCreateCellLocalCoords_DA_Q1_Gauss(PetscInt dim,PetscInt np_1d,PetscInt *_npoints,PetscReal **_xi)
770e2ec84fSDave May {
780e2ec84fSDave May   PetscErrorCode ierr;
790e2ec84fSDave May   PetscQuadrature quadrature;
800e2ec84fSDave May   const PetscReal *quadrature_xi;
810e2ec84fSDave May   PetscReal *xi;
820e2ec84fSDave May   PetscInt d,q,npoints_q;
830e2ec84fSDave May 
840e2ec84fSDave May   PetscFunctionBegin;
850e2ec84fSDave May   ierr = PetscDTGaussTensorQuadrature(dim,np_1d,-1.0,1.0,&quadrature);CHKERRQ(ierr);
860e2ec84fSDave May   ierr = PetscQuadratureGetData(quadrature,NULL,&npoints_q,&quadrature_xi,NULL);CHKERRQ(ierr);
870e2ec84fSDave May   ierr = PetscMalloc1(dim*npoints_q,&xi);CHKERRQ(ierr);
880e2ec84fSDave May   for (q=0; q<npoints_q; q++) {
890e2ec84fSDave May     for (d=0; d<dim; d++) {
900e2ec84fSDave May       xi[dim*q+d] = quadrature_xi[dim*q+d];
910e2ec84fSDave May     }
920e2ec84fSDave May   }
930e2ec84fSDave May   ierr = PetscQuadratureDestroy(&quadrature);CHKERRQ(ierr);
940e2ec84fSDave May 
950e2ec84fSDave May   *_npoints = npoints_q;
960e2ec84fSDave May   *_xi = xi;
970e2ec84fSDave May 
980e2ec84fSDave May   PetscFunctionReturn(0);
990e2ec84fSDave May }
1000e2ec84fSDave May 
101d3393ee1SDave May PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA_Q1(DM dm,DM dmc,PetscInt npoints,DMSwarmPICLayoutType layout)
1020e2ec84fSDave May {
1030e2ec84fSDave May   PetscErrorCode ierr;
1040e2ec84fSDave May   PetscInt dim,npoints_q;
1050e2ec84fSDave May   PetscInt nel,npe,e,q,k,d;
1060e2ec84fSDave May   const PetscInt *element_list;
1070e2ec84fSDave May   PetscReal **basis;
1080e2ec84fSDave May   PetscReal *xi;
1090e2ec84fSDave May   Vec coor;
1100e2ec84fSDave May   const PetscScalar *_coor;
1110e2ec84fSDave May   PetscReal *elcoor;
1120e2ec84fSDave May   PetscReal *swarm_coor;
1130e2ec84fSDave May   PetscInt *swarm_cellid;
1140e2ec84fSDave May   PetscInt pcnt;
1150e2ec84fSDave May 
1160e2ec84fSDave May   PetscFunctionBegin;
1170e2ec84fSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1180e2ec84fSDave May   switch (layout) {
1190e2ec84fSDave May     case DMSWARMPIC_LAYOUT_REGULAR:
1200e2ec84fSDave May     {
1210e2ec84fSDave May       PetscInt np_dir[3];
1220e2ec84fSDave May       np_dir[0] = np_dir[1] = np_dir[2] = npoints;
1230e2ec84fSDave May       ierr = private_DMSwarmCreateCellLocalCoords_DA_Q1_Regular(dim,np_dir,&npoints_q,&xi);CHKERRQ(ierr);
1240e2ec84fSDave May     }
1250e2ec84fSDave May       break;
1260e2ec84fSDave May     case DMSWARMPIC_LAYOUT_GAUSS:
1270e2ec84fSDave May       ierr = private_DMSwarmCreateCellLocalCoords_DA_Q1_Gauss(dim,npoints,&npoints_q,&xi);CHKERRQ(ierr);
1280e2ec84fSDave May       break;
129d3393ee1SDave May 
130d3393ee1SDave May     case DMSWARMPIC_LAYOUT_SUBDIVISION:
131d3393ee1SDave May     {
132d3393ee1SDave May       PetscInt s,nsub;
133d3393ee1SDave May       PetscInt np_dir[3];
134d3393ee1SDave May       nsub = npoints;
135d3393ee1SDave May       np_dir[0] = 1;
136d3393ee1SDave May       for (s=0; s<nsub; s++) {
137d3393ee1SDave May         np_dir[0] *= 2;
138d3393ee1SDave May       }
139d3393ee1SDave May       np_dir[1] = np_dir[0];
140d3393ee1SDave May       np_dir[2] = np_dir[0];
141d3393ee1SDave May       ierr = private_DMSwarmCreateCellLocalCoords_DA_Q1_Regular(dim,np_dir,&npoints_q,&xi);CHKERRQ(ierr);
142d3393ee1SDave May     }
143d3393ee1SDave May       break;
1440e2ec84fSDave May     default:
1450e2ec84fSDave May       SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"A valid DMSwarmPIC layout must be provided");
1460e2ec84fSDave May       break;
1470e2ec84fSDave May   }
1480e2ec84fSDave May 
1490e2ec84fSDave May   ierr = DMDAGetElements(dmc,&nel,&npe,&element_list);CHKERRQ(ierr);
1500e2ec84fSDave May 
1510e2ec84fSDave May   ierr = PetscMalloc1(dim*npe,&elcoor);CHKERRQ(ierr);
1520e2ec84fSDave May   ierr = PetscMalloc1(npoints_q,&basis);CHKERRQ(ierr);
1530e2ec84fSDave May   for (q=0; q<npoints_q; q++) {
1540e2ec84fSDave May     ierr = PetscMalloc1(npe,&basis[q]);CHKERRQ(ierr);
1550e2ec84fSDave May 
1560e2ec84fSDave May     switch (dim) {
1570e2ec84fSDave May       case 1:
1580e2ec84fSDave May         basis[q][0] = 0.5*(1.0 - xi[dim*q+0]);
1590e2ec84fSDave May         basis[q][1] = 0.5*(1.0 + xi[dim*q+0]);
1600e2ec84fSDave May         break;
1610e2ec84fSDave May       case 2:
1620e2ec84fSDave May         basis[q][0] = 0.25*(1.0 - xi[dim*q+0])*(1.0 - xi[dim*q+1]);
1630e2ec84fSDave May         basis[q][1] = 0.25*(1.0 + xi[dim*q+0])*(1.0 - xi[dim*q+1]);
1640e2ec84fSDave May         basis[q][2] = 0.25*(1.0 + xi[dim*q+0])*(1.0 + xi[dim*q+1]);
1650e2ec84fSDave May         basis[q][3] = 0.25*(1.0 - xi[dim*q+0])*(1.0 + xi[dim*q+1]);
1660e2ec84fSDave May         break;
1670e2ec84fSDave May 
1680e2ec84fSDave May       case 3:
1690e2ec84fSDave May         basis[q][0] = 0.125*(1.0 - xi[dim*q+0])*(1.0 - xi[dim*q+1])*(1.0 - xi[dim*q+2]);
1700e2ec84fSDave May         basis[q][1] = 0.125*(1.0 + xi[dim*q+0])*(1.0 - xi[dim*q+1])*(1.0 - xi[dim*q+2]);
1710e2ec84fSDave May         basis[q][2] = 0.125*(1.0 + xi[dim*q+0])*(1.0 + xi[dim*q+1])*(1.0 - xi[dim*q+2]);
1720e2ec84fSDave May         basis[q][3] = 0.125*(1.0 - xi[dim*q+0])*(1.0 + xi[dim*q+1])*(1.0 - xi[dim*q+2]);
1730e2ec84fSDave May         basis[q][4] = 0.125*(1.0 - xi[dim*q+0])*(1.0 - xi[dim*q+1])*(1.0 + xi[dim*q+2]);
1740e2ec84fSDave May         basis[q][5] = 0.125*(1.0 + xi[dim*q+0])*(1.0 - xi[dim*q+1])*(1.0 + xi[dim*q+2]);
1750e2ec84fSDave May         basis[q][6] = 0.125*(1.0 + xi[dim*q+0])*(1.0 + xi[dim*q+1])*(1.0 + xi[dim*q+2]);
1760e2ec84fSDave May         basis[q][7] = 0.125*(1.0 - xi[dim*q+0])*(1.0 + xi[dim*q+1])*(1.0 + xi[dim*q+2]);
1770e2ec84fSDave May         break;
1780e2ec84fSDave May     }
1790e2ec84fSDave May   }
1800e2ec84fSDave May 
1810e2ec84fSDave May   ierr = DMSwarmSetLocalSizes(dm,npoints_q*nel,-1);CHKERRQ(ierr);
1820e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
1830e2ec84fSDave May   ierr = DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
1840e2ec84fSDave May 
1850e2ec84fSDave May   ierr = DMGetCoordinatesLocal(dmc,&coor);CHKERRQ(ierr);
1860e2ec84fSDave May   ierr = VecGetArrayRead(coor,&_coor);CHKERRQ(ierr);
1870e2ec84fSDave May   pcnt = 0;
1880e2ec84fSDave May   for (e=0; e<nel; e++) {
1890e2ec84fSDave May     const PetscInt *element = &element_list[npe*e];
1900e2ec84fSDave May 
1910e2ec84fSDave May     for (k=0; k<npe; k++) {
1920e2ec84fSDave May       for (d=0; d<dim; d++) {
1930e2ec84fSDave May         elcoor[dim*k+d] = _coor[ dim*element[k] + d ];
1940e2ec84fSDave May       }
1950e2ec84fSDave May     }
1960e2ec84fSDave May 
1970e2ec84fSDave May     for (q=0; q<npoints_q; q++) {
1980e2ec84fSDave May       for (d=0; d<dim; d++) {
1990e2ec84fSDave May         swarm_coor[dim*pcnt+d] = 0.0;
2000e2ec84fSDave May       }
2010e2ec84fSDave May       for (k=0; k<npe; k++) {
2020e2ec84fSDave May         for (d=0; d<dim; d++) {
2030e2ec84fSDave May           swarm_coor[dim*pcnt+d] += basis[q][k] * elcoor[dim*k+d];
2040e2ec84fSDave May         }
2050e2ec84fSDave May       }
2060e2ec84fSDave May       swarm_cellid[pcnt] = e;
2070e2ec84fSDave May       pcnt++;
2080e2ec84fSDave May     }
2090e2ec84fSDave May   }
2100e2ec84fSDave May   ierr = VecRestoreArrayRead(coor,&_coor);CHKERRQ(ierr);
2110e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);CHKERRQ(ierr);
2120e2ec84fSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);CHKERRQ(ierr);
2130e2ec84fSDave May   ierr = DMDARestoreElements(dmc,&nel,&npe,&element_list);CHKERRQ(ierr);
2140e2ec84fSDave May 
2150e2ec84fSDave May   ierr = PetscFree(xi);CHKERRQ(ierr);
2160e2ec84fSDave May   ierr = PetscFree(elcoor);CHKERRQ(ierr);
2170e2ec84fSDave May   for (q=0; q<npoints_q; q++) {
2180e2ec84fSDave May     ierr = PetscFree(basis[q]);CHKERRQ(ierr);
2190e2ec84fSDave May   }
2200e2ec84fSDave May   ierr = PetscFree(basis);CHKERRQ(ierr);
2210e2ec84fSDave May 
2220e2ec84fSDave May   PetscFunctionReturn(0);
2230e2ec84fSDave May }
2240e2ec84fSDave May 
2250e2ec84fSDave May PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_DA(DM dm,DM celldm,DMSwarmPICLayoutType layout,PetscInt layout_param)
2260e2ec84fSDave May {
2270e2ec84fSDave May   PetscErrorCode ierr;
2280e2ec84fSDave May   DMDAElementType etype;
2290e2ec84fSDave May   PetscInt dim;
2300e2ec84fSDave May 
2310e2ec84fSDave May   PetscFunctionBegin;
2320e2ec84fSDave May   ierr = DMDAGetElementType(celldm,&etype);CHKERRQ(ierr);
2330e2ec84fSDave May   ierr = DMGetDimension(celldm,&dim);CHKERRQ(ierr);
2340e2ec84fSDave May   switch (etype) {
2350e2ec84fSDave May     case DMDA_ELEMENT_P1:
2360e2ec84fSDave May       SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DA support is not currently available for DMDA_ELEMENT_P1");
2370e2ec84fSDave May       break;
2380e2ec84fSDave May     case DMDA_ELEMENT_Q1:
2390e2ec84fSDave May       if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Support only available for dim = 2, 3");
2400e2ec84fSDave May       ierr = private_DMSwarmInsertPointsUsingCellDM_DA_Q1(dm,celldm,layout_param,layout);CHKERRQ(ierr);
2410e2ec84fSDave May       break;
2420e2ec84fSDave May   }
2430e2ec84fSDave May   PetscFunctionReturn(0);
2440e2ec84fSDave May }
245*1f52046fSDave May 
246*1f52046fSDave May PetscErrorCode DMSwarmProjectField_ApproxQ1_DA_2D(DM swarm,PetscReal *swarm_field,DM dm,Vec v_field)
247*1f52046fSDave May {
248*1f52046fSDave May   PetscErrorCode ierr;
249*1f52046fSDave May   Vec v_field_l,denom_l,coor_l,denom;
250*1f52046fSDave May   PetscReal *_field_l,*_denom_l;
251*1f52046fSDave May   PetscInt k,p,e,npoints,nel,npe;
252*1f52046fSDave May   PetscInt *mpfield_cell;
253*1f52046fSDave May   PetscReal *mpfield_coor;
254*1f52046fSDave May   const PetscInt *element_list;
255*1f52046fSDave May   const PetscInt *element;
256*1f52046fSDave May   PetscReal xi_p[2],Ni[4];
257*1f52046fSDave May   const PetscReal *_coor;
258*1f52046fSDave May 
259*1f52046fSDave May   PetscFunctionBegin;
260*1f52046fSDave May   ierr = VecZeroEntries(v_field);CHKERRQ(ierr);
261*1f52046fSDave May 
262*1f52046fSDave May   ierr = DMGetLocalVector(dm,&v_field_l);CHKERRQ(ierr);
263*1f52046fSDave May   ierr = DMGetGlobalVector(dm,&denom);CHKERRQ(ierr);
264*1f52046fSDave May   ierr = DMGetLocalVector(dm,&denom_l);CHKERRQ(ierr);
265*1f52046fSDave May   ierr = VecZeroEntries(v_field_l);CHKERRQ(ierr);
266*1f52046fSDave May   ierr = VecZeroEntries(denom);CHKERRQ(ierr);
267*1f52046fSDave May   ierr = VecZeroEntries(denom_l);CHKERRQ(ierr);
268*1f52046fSDave May 
269*1f52046fSDave May   ierr = VecGetArray(v_field_l,&_field_l);CHKERRQ(ierr);
270*1f52046fSDave May   ierr = VecGetArray(denom_l,&_denom_l);CHKERRQ(ierr);
271*1f52046fSDave May 
272*1f52046fSDave May   ierr = DMGetCoordinatesLocal(dm,&coor_l);CHKERRQ(ierr);
273*1f52046fSDave May   ierr = VecGetArrayRead(coor_l,&_coor);CHKERRQ(ierr);
274*1f52046fSDave May 
275*1f52046fSDave May   ierr = DMDAGetElements(dm,&nel,&npe,&element_list);CHKERRQ(ierr);
276*1f52046fSDave May   ierr = DMSwarmGetLocalSize(swarm,&npoints);CHKERRQ(ierr);
277*1f52046fSDave May   ierr = DMSwarmGetField(swarm,DMSwarmPICField_coor,NULL,NULL,(void**)&mpfield_coor);CHKERRQ(ierr);
278*1f52046fSDave May   ierr = DMSwarmGetField(swarm,DMSwarmPICField_cellid,NULL,NULL,(void**)&mpfield_cell);CHKERRQ(ierr);
279*1f52046fSDave May 
280*1f52046fSDave May   for (p=0; p<npoints; p++) {
281*1f52046fSDave May     PetscReal *coor_p;
282*1f52046fSDave May     const PetscReal *x0;
283*1f52046fSDave May     const PetscReal *x2;
284*1f52046fSDave May     PetscReal dx[2];
285*1f52046fSDave May 
286*1f52046fSDave May     e = mpfield_cell[p];
287*1f52046fSDave May     coor_p = &mpfield_coor[2*p];
288*1f52046fSDave May     element = &element_list[npe*e];
289*1f52046fSDave May 
290*1f52046fSDave May     /* compute local coordinates: (xp-x0)/dx = (xip+1)/2 */
291*1f52046fSDave May     x0 = &_coor[2*element[0]];
292*1f52046fSDave May     x2 = &_coor[2*element[2]];
293*1f52046fSDave May 
294*1f52046fSDave May     dx[0] = x2[0] - x0[0];
295*1f52046fSDave May     dx[1] = x2[1] - x0[1];
296*1f52046fSDave May 
297*1f52046fSDave May     xi_p[0] = 2.0 * (coor_p[0] - x0[0])/dx[0] - 1.0;
298*1f52046fSDave May     xi_p[1] = 2.0 * (coor_p[1] - x0[1])/dx[1] - 1.0;
299*1f52046fSDave May 
300*1f52046fSDave May     /* evaluate basis functions */
301*1f52046fSDave May     Ni[0] = 0.25*(1.0 - xi_p[0])*(1.0 - xi_p[1]);
302*1f52046fSDave May     Ni[1] = 0.25*(1.0 + xi_p[0])*(1.0 - xi_p[1]);
303*1f52046fSDave May     Ni[2] = 0.25*(1.0 + xi_p[0])*(1.0 + xi_p[1]);
304*1f52046fSDave May     Ni[3] = 0.25*(1.0 - xi_p[0])*(1.0 + xi_p[1]);
305*1f52046fSDave May 
306*1f52046fSDave May     for (k=0; k<npe; k++) {
307*1f52046fSDave May       _field_l[ element[k] ] += Ni[k] * swarm_field[p];
308*1f52046fSDave May       _denom_l[ element[k] ] += Ni[k];
309*1f52046fSDave May     }
310*1f52046fSDave May   }
311*1f52046fSDave May 
312*1f52046fSDave May   ierr = DMSwarmRestoreField(swarm,DMSwarmPICField_cellid,NULL,NULL,(void**)&mpfield_cell);CHKERRQ(ierr);
313*1f52046fSDave May   ierr = DMSwarmRestoreField(swarm,DMSwarmPICField_coor,NULL,NULL,(void**)&mpfield_coor);CHKERRQ(ierr);
314*1f52046fSDave May   ierr = DMDARestoreElements(dm,&nel,&npe,&element_list);CHKERRQ(ierr);
315*1f52046fSDave May   ierr = VecRestoreArrayRead(coor_l,&_coor);CHKERRQ(ierr);
316*1f52046fSDave May   ierr = VecRestoreArray(v_field_l,&_field_l);CHKERRQ(ierr);
317*1f52046fSDave May   ierr = VecRestoreArray(denom_l,&_denom_l);CHKERRQ(ierr);
318*1f52046fSDave May 
319*1f52046fSDave May   ierr = DMLocalToGlobalBegin(dm,v_field_l,ADD_VALUES,v_field);CHKERRQ(ierr);
320*1f52046fSDave May   ierr = DMLocalToGlobalEnd(dm,v_field_l,ADD_VALUES,v_field);CHKERRQ(ierr);
321*1f52046fSDave May   ierr = DMLocalToGlobalBegin(dm,denom_l,ADD_VALUES,denom);CHKERRQ(ierr);
322*1f52046fSDave May   ierr = DMLocalToGlobalEnd(dm,denom_l,ADD_VALUES,denom);CHKERRQ(ierr);
323*1f52046fSDave May 
324*1f52046fSDave May   ierr = VecPointwiseDivide(v_field,v_field,denom);CHKERRQ(ierr);
325*1f52046fSDave May 
326*1f52046fSDave May   ierr = DMRestoreLocalVector(dm,&v_field_l);CHKERRQ(ierr);
327*1f52046fSDave May   ierr = DMRestoreLocalVector(dm,&denom_l);CHKERRQ(ierr);
328*1f52046fSDave May   ierr = DMRestoreGlobalVector(dm,&denom);CHKERRQ(ierr);
329*1f52046fSDave May 
330*1f52046fSDave May   PetscFunctionReturn(0);
331*1f52046fSDave May }
332*1f52046fSDave May 
333*1f52046fSDave May PetscErrorCode private_DMSwarmProjectFields_DA(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DataField dfield[],Vec vecs[])
334*1f52046fSDave May {
335*1f52046fSDave May   PetscErrorCode ierr;
336*1f52046fSDave May   PetscInt f,dim;
337*1f52046fSDave May   DMDAElementType etype;
338*1f52046fSDave May 
339*1f52046fSDave May   PetscFunctionBegin;
340*1f52046fSDave May   ierr = DMDAGetElementType(celldm,&etype);CHKERRQ(ierr);
341*1f52046fSDave May   if (etype == DMDA_ELEMENT_P1) SETERRQ(PetscObjectComm((PetscObject)swarm),PETSC_ERR_SUP,"Only Q1 DMDA supported");
342*1f52046fSDave May 
343*1f52046fSDave May   ierr = DMGetDimension(swarm,&dim);CHKERRQ(ierr);
344*1f52046fSDave May   switch (dim) {
345*1f52046fSDave May     case 2:
346*1f52046fSDave May       for (f=0; f<nfields; f++) {
347*1f52046fSDave May         PetscReal *swarm_field;
348*1f52046fSDave May 
349*1f52046fSDave May         ierr = DataFieldGetEntries(dfield[f],(void**)&swarm_field);CHKERRQ(ierr);
350*1f52046fSDave May         ierr = DMSwarmProjectField_ApproxQ1_DA_2D(swarm,swarm_field,celldm,vecs[f]);CHKERRQ(ierr);
351*1f52046fSDave May       }
352*1f52046fSDave May       break;
353*1f52046fSDave May     case 3:
354*1f52046fSDave May       SETERRQ(PetscObjectComm((PetscObject)swarm),PETSC_ERR_SUP,"No support for 3D");
355*1f52046fSDave May       break;
356*1f52046fSDave May     default:
357*1f52046fSDave May       break;
358*1f52046fSDave May   }
359*1f52046fSDave May   PetscFunctionReturn(0);
360*1f52046fSDave May }
361