Actual source code: swarmpic_plex.c

petsc-3.9.4 2018-09-11
Report Typos and Errors
  1:  #include <petscdm.h>
  2:  #include <petscdmplex.h>
  3:  #include <petscdmswarm.h>
  4: #include "../src/dm/impls/swarm/data_bucket.h"


  7: PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM,DM,PetscInt,PetscReal*xi);

  9: static PetscErrorCode private_PetscFECreateDefault_scalar_pk1(DM dm, PetscInt dim, PetscBool isSimplex, PetscInt qorder, PetscFE *fem)
 10: {
 11:   const PetscInt Nc = 1;
 12:   PetscQuadrature q, fq;
 13:   DM              K;
 14:   PetscSpace      P;
 15:   PetscDualSpace  Q;
 16:   PetscInt        order, quadPointsPerEdge;
 17:   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
 18:   PetscErrorCode  ierr;

 21:   /* Create space */
 22:   PetscSpaceCreate(PetscObjectComm((PetscObject) dm), &P);
 23:   /*PetscObjectSetOptionsPrefix((PetscObject) P, prefix);*/
 24:   PetscSpacePolynomialSetTensor(P, tensor);
 25:   /*PetscSpaceSetFromOptions(P);*/
 26:   PetscSpaceSetType(P,PETSCSPACEPOLYNOMIAL);
 27:   PetscSpaceSetOrder(P,1);
 28:   PetscSpaceSetNumComponents(P, Nc);
 29:   PetscSpacePolynomialSetNumVariables(P, dim);
 30:   PetscSpaceSetUp(P);
 31:   PetscSpaceGetOrder(P, &order);
 32:   PetscSpacePolynomialGetTensor(P, &tensor);
 33:   /* Create dual space */
 34:   PetscDualSpaceCreate(PetscObjectComm((PetscObject) dm), &Q);
 35:   PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);
 36:   /*PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);*/
 37:   PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);
 38:   PetscDualSpaceSetDM(Q, K);
 39:   DMDestroy(&K);
 40:   PetscDualSpaceSetNumComponents(Q, Nc);
 41:   PetscDualSpaceSetOrder(Q, order);
 42:   PetscDualSpaceLagrangeSetTensor(Q, tensor);
 43:   /*PetscDualSpaceSetFromOptions(Q);*/
 44:   PetscDualSpaceSetType(Q,PETSCDUALSPACELAGRANGE);
 45:   PetscDualSpaceSetUp(Q);
 46:   /* Create element */
 47:   PetscFECreate(PetscObjectComm((PetscObject) dm), fem);
 48:   /*PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);*/
 49:   /*PetscFESetFromOptions(*fem);*/
 50:   PetscFESetType(*fem,PETSCFEBASIC);
 51:   PetscFESetBasisSpace(*fem, P);
 52:   PetscFESetDualSpace(*fem, Q);
 53:   PetscFESetNumComponents(*fem, Nc);
 54:   PetscFESetUp(*fem);
 55:   PetscSpaceDestroy(&P);
 56:   PetscDualSpaceDestroy(&Q);
 57:   /* Create quadrature (with specified order if given) */
 58:   qorder = qorder >= 0 ? qorder : order;
 59:   quadPointsPerEdge = PetscMax(qorder + 1,1);
 60:   if (isSimplex) {
 61:     PetscDTGaussJacobiQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);
 62:     PetscDTGaussJacobiQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);
 63:   }
 64:   else {
 65:     PetscDTGaussTensorQuadrature(dim,   1, quadPointsPerEdge, -1.0, 1.0, &q);
 66:     PetscDTGaussTensorQuadrature(dim-1, 1, quadPointsPerEdge, -1.0, 1.0, &fq);
 67:   }
 68:   PetscFESetQuadrature(*fem, q);
 69:   PetscFESetFaceQuadrature(*fem, fq);
 70:   PetscQuadratureDestroy(&q);
 71:   PetscQuadratureDestroy(&fq);
 72:   return(0);
 73: }

 75: PetscErrorCode subdivide_triangle(PetscReal v1[2],PetscReal v2[2],PetscReal v3[3],PetscInt depth,PetscInt max,PetscReal xi[],PetscInt *np)
 76: {
 77:   PetscReal v12[2],v23[2],v31[2];
 78:   PetscInt i;
 80: 
 82:   if (depth == max) {
 83:     PetscReal cx[2];
 84: 
 85:     cx[0] = (v1[0] + v2[0] + v3[0])/3.0;
 86:     cx[1] = (v1[1] + v2[1] + v3[1])/3.0;
 87: 
 88:     xi[2*(*np)+0] = cx[0];
 89:     xi[2*(*np)+1] = cx[1];
 90:     (*np)++;
 91:     return(0);
 92:   }
 93: 
 94:   /* calculate midpoints of each side */
 95:   for (i = 0; i < 2; i++) {
 96:     v12[i] = (v1[i]+v2[i])/2.0;
 97:     v23[i] = (v2[i]+v3[i])/2.0;
 98:     v31[i] = (v3[i]+v1[i])/2.0;
 99:   }
100: 
101:   /* recursively subdivide new triangles */
102:   subdivide_triangle(v1,v12,v31,depth+1,max,xi,np);
103:   subdivide_triangle(v2,v23,v12,depth+1,max,xi,np);
104:   subdivide_triangle(v3,v31,v23,depth+1,max,xi,np);
105:   subdivide_triangle(v12,v23,v31,depth+1,max,xi,np);
106:   return(0);
107: }


110: PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX2D_SubDivide(DM dm,DM dmc,PetscInt nsub)
111: {
113:   const PetscInt dim = 2;
114:   PetscInt q,npoints_q,e,nel,npe,pcnt,ps,pe,d,k,depth;
115:   PetscReal *xi;
116:   PetscReal **basis;
117:   Vec coorlocal;
118:   PetscSection coordSection;
119:   PetscScalar *elcoor = NULL;
120:   PetscReal *swarm_coor;
121:   PetscInt *swarm_cellid;
122:   PetscReal v1[2],v2[2],v3[2];
123: 
125: 
126:   npoints_q = 1;
127:   for (d=0; d<nsub; d++) { npoints_q *= 4; }
128:   PetscMalloc1(dim*npoints_q,&xi);
129: 
130:   v1[0] = 0.0;  v1[1] = 0.0;
131:   v2[0] = 1.0;  v2[1] = 0.0;
132:   v3[0] = 0.0;  v3[1] = 1.0;
133:   depth = 0;
134:   pcnt = 0;
135:   subdivide_triangle(v1,v2,v3,depth,nsub,xi,&pcnt);

137:   npe = 3; /* nodes per element (triangle) */
138:   PetscMalloc1(npoints_q,&basis);
139:   for (q=0; q<npoints_q; q++) {
140:     PetscMalloc1(npe,&basis[q]);
141: 
142:     basis[q][0] = 1.0 - xi[dim*q+0] - xi[dim*q+1];
143:     basis[q][1] = xi[dim*q+0];
144:     basis[q][2] = xi[dim*q+1];
145:   }
146: 
147:   /* 0->cell, 1->edge, 2->vert */
148:   DMPlexGetHeightStratum(dmc,0,&ps,&pe);
149:   nel = pe - ps;
150: 
151:   DMSwarmSetLocalSizes(dm,npoints_q*nel,-1);
152:   DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
153:   DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
154: 
155:   DMGetCoordinatesLocal(dmc,&coorlocal);
156:   DMGetCoordinateSection(dmc,&coordSection);
157: 
158:   pcnt = 0;
159:   for (e=0; e<nel; e++) {
160:     DMPlexVecGetClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
161: 
162:     for (q=0; q<npoints_q; q++) {
163:       for (d=0; d<dim; d++) {
164:         swarm_coor[dim*pcnt+d] = 0.0;
165:         for (k=0; k<npe; k++) {
166:           swarm_coor[dim*pcnt+d] += basis[q][k] * PetscRealPart(elcoor[dim*k+d]);
167:         }
168:       }
169:       swarm_cellid[pcnt] = e;
170:       pcnt++;
171:     }
172:     DMPlexVecRestoreClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
173:   }
174:   DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
175:   DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
176: 
177:   PetscFree(xi);
178:   for (q=0; q<npoints_q; q++) {
179:     PetscFree(basis[q]);
180:   }
181:   PetscFree(basis);
182: 
183:   return(0);
184: }

186: PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX_SubDivide(DM dm,DM dmc,PetscInt nsub)
187: {
189:   PetscInt dim,nfaces,nbasis;
190:   PetscInt q,npoints_q,e,nel,pcnt,ps,pe,d,k,r;
191:   PetscReal *B;
192:   Vec coorlocal;
193:   PetscSection coordSection;
194:   PetscScalar *elcoor = NULL;
195:   PetscReal *swarm_coor;
196:   PetscInt *swarm_cellid;
197:   const PetscReal *xiq;
198:   PetscQuadrature quadrature;
199:   PetscFE fe,feRef;
200:   PetscBool is_simplex;
201: 
203: 
204:   DMGetDimension(dmc,&dim);
205: 
206:   is_simplex = PETSC_FALSE;
207:   DMPlexGetHeightStratum(dmc,0,&ps,&pe);
208:   DMPlexGetConeSize(dmc, ps, &nfaces);
209:   if (nfaces == (dim+1)) { is_simplex = PETSC_TRUE; }
210: 
211:   private_PetscFECreateDefault_scalar_pk1(dmc, dim, is_simplex, 0, &fe);
212: 
213:   for (r=0; r<nsub; r++) {
214:     PetscFERefine(fe,&feRef);
215:     PetscFEGetQuadrature(feRef,&quadrature);
216:     PetscFESetQuadrature(fe,quadrature);
217:     PetscFEDestroy(&feRef);
218:   }

220:   PetscFEGetQuadrature(fe,&quadrature);
221:   PetscQuadratureGetData(quadrature, NULL, NULL, &npoints_q, &xiq, NULL);
222:   PetscFEGetDimension(fe,&nbasis);
223:   PetscFEGetDefaultTabulation(fe, &B, NULL, NULL);
224: 
225:   /* 0->cell, 1->edge, 2->vert */
226:   DMPlexGetHeightStratum(dmc,0,&ps,&pe);
227:   nel = pe - ps;
228: 
229:   DMSwarmSetLocalSizes(dm,npoints_q*nel,-1);
230:   DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
231:   DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
232: 
233:   DMGetCoordinatesLocal(dmc,&coorlocal);
234:   DMGetCoordinateSection(dmc,&coordSection);
235: 
236:   pcnt = 0;
237:   for (e=0; e<nel; e++) {
238:     DMPlexVecGetClosure(dmc,coordSection,coorlocal,ps+e,NULL,&elcoor);
239: 
240:     for (q=0; q<npoints_q; q++) {
241:       for (d=0; d<dim; d++) {
242:         swarm_coor[dim*pcnt+d] = 0.0;
243:         for (k=0; k<nbasis; k++) {
244:           swarm_coor[dim*pcnt+d] += B[q*nbasis + k] * PetscRealPart(elcoor[dim*k+d]);
245:         }
246:       }
247:       swarm_cellid[pcnt] = e;
248:       pcnt++;
249:     }
250:     DMPlexVecRestoreClosure(dmc,coordSection,coorlocal,ps+e,NULL,&elcoor);
251:   }
252:   DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
253:   DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
254: 
255:   PetscFEDestroy(&fe);
256:   return(0);
257: }

259: PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX2D_Regular(DM dm,DM dmc,PetscInt npoints)
260: {
262:   PetscInt dim;
263:   PetscInt ii,jj,q,npoints_q,e,nel,npe,pcnt,ps,pe,d,k,nfaces;
264:   PetscReal *xi,ds,ds2;
265:   PetscReal **basis;
266:   Vec coorlocal;
267:   PetscSection coordSection;
268:   PetscScalar *elcoor = NULL;
269:   PetscReal *swarm_coor;
270:   PetscInt *swarm_cellid;
271:   PetscBool is_simplex;
272: 
274:   DMGetDimension(dmc,&dim);
275:   if (dim != 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only 2D is supported");
276:   is_simplex = PETSC_FALSE;
277:   DMPlexGetHeightStratum(dmc,0,&ps,&pe);
278:   DMPlexGetConeSize(dmc, ps, &nfaces);
279:   if (nfaces == (dim+1)) { is_simplex = PETSC_TRUE; }
280:   if (!is_simplex) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only the simplex is supported");

282:   PetscMalloc1(dim*npoints*npoints,&xi);
283:   pcnt = 0;
284:   ds = 1.0/((PetscReal)(npoints-1));
285:   ds2 = 1.0/((PetscReal)(npoints));
286:   for (jj = 0; jj<npoints; jj++) {
287:     for (ii=0; ii<npoints-jj; ii++) {
288:       xi[dim*pcnt+0] = ii * ds;
289:       xi[dim*pcnt+1] = jj * ds;
290: 
291:       xi[dim*pcnt+0] *= (1.0 - 1.2*ds2);
292:       xi[dim*pcnt+1] *= (1.0 - 1.2*ds2);
293: 
294:       xi[dim*pcnt+0] += 0.35*ds2;
295:       xi[dim*pcnt+1] += 0.35*ds2;

297:       pcnt++;
298:     }
299:   }
300:   npoints_q = pcnt;
301: 
302:   npe = 3; /* nodes per element (triangle) */
303:   PetscMalloc1(npoints_q,&basis);
304:   for (q=0; q<npoints_q; q++) {
305:     PetscMalloc1(npe,&basis[q]);
306: 
307:     basis[q][0] = 1.0 - xi[dim*q+0] - xi[dim*q+1];
308:     basis[q][1] = xi[dim*q+0];
309:     basis[q][2] = xi[dim*q+1];
310:   }

312:   /* 0->cell, 1->edge, 2->vert */
313:   DMPlexGetHeightStratum(dmc,0,&ps,&pe);
314:   nel = pe - ps;
315: 
316:   DMSwarmSetLocalSizes(dm,npoints_q*nel,-1);
317:   DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
318:   DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
319: 
320:   DMGetCoordinatesLocal(dmc,&coorlocal);
321:   DMGetCoordinateSection(dmc,&coordSection);

323:   pcnt = 0;
324:   for (e=0; e<nel; e++) {
325:     DMPlexVecGetClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
326: 
327:     for (q=0; q<npoints_q; q++) {
328:       for (d=0; d<dim; d++) {
329:         swarm_coor[dim*pcnt+d] = 0.0;
330:         for (k=0; k<npe; k++) {
331:           swarm_coor[dim*pcnt+d] += basis[q][k] * PetscRealPart(elcoor[dim*k+d]);
332:         }
333:       }
334:       swarm_cellid[pcnt] = e;
335:       pcnt++;
336:     }
337:     DMPlexVecRestoreClosure(dmc,coordSection,coorlocal,e,NULL,&elcoor);
338:   }
339:   DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
340:   DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
341: 
342:   PetscFree(xi);
343:   for (q=0; q<npoints_q; q++) {
344:     PetscFree(basis[q]);
345:   }
346:   PetscFree(basis);
347: 
348:   return(0);
349: }

351: PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM dm,DM celldm,DMSwarmPICLayoutType layout,PetscInt layout_param)
352: {
354:   PetscInt dim;
355: 
357:   DMGetDimension(celldm,&dim);
358:   switch (layout) {
359:     case DMSWARMPIC_LAYOUT_REGULAR:
360:       if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"No 3D support for REGULAR+PLEX");
361:       private_DMSwarmInsertPointsUsingCellDM_PLEX2D_Regular(dm,celldm,layout_param);
362:       break;
363:     case DMSWARMPIC_LAYOUT_GAUSS:
364:     {
365:       PetscInt npoints,npoints1,ps,pe,nfaces;
366:       const PetscReal *xi;
367:       PetscBool is_simplex;
368:       PetscQuadrature quadrature;
369: 
370:       is_simplex = PETSC_FALSE;
371:       DMPlexGetHeightStratum(celldm,0,&ps,&pe);
372:       DMPlexGetConeSize(celldm, ps, &nfaces);
373:       if (nfaces == (dim+1)) { is_simplex = PETSC_TRUE; }

375:       npoints1 = layout_param;
376:       if (is_simplex) {
377:         PetscDTGaussJacobiQuadrature(dim,1,npoints1,-1.0,1.0,&quadrature);
378:       } else {
379:         PetscDTGaussTensorQuadrature(dim,1,npoints1,-1.0,1.0,&quadrature);
380:       }
381:       PetscQuadratureGetData(quadrature,NULL,NULL,&npoints,&xi,NULL);
382:       private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm,celldm,npoints,(PetscReal*)xi);
383:       PetscQuadratureDestroy(&quadrature);
384:     }
385:       break;
386:     case DMSWARMPIC_LAYOUT_SUBDIVISION:
387:       private_DMSwarmInsertPointsUsingCellDM_PLEX_SubDivide(dm,celldm,layout_param);
388:       break;
389:   }
390:   return(0);
391: }

393: /*
394: typedef struct {
395:   PetscReal x,y;
396: } Point2d;

398: static PetscErrorCode signp2d(Point2d p1, Point2d p2, Point2d p3,PetscReal *s)
399: {
401:   *s = (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
402:   return(0);
403: }
404: */
405: /*
406: static PetscErrorCode PointInTriangle(Point2d pt, Point2d v1, Point2d v2, Point2d v3,PetscBool *v)
407: {
408:   PetscReal s1,s2,s3;
409:   PetscBool b1, b2, b3;
410: 
412:   signp2d(pt, v1, v2,&s1); b1 = s1 < 0.0f;
413:   signp2d(pt, v2, v3,&s2); b2 = s2 < 0.0f;
414:   signp2d(pt, v3, v1,&s3); b3 = s3 < 0.0f;
415: 
416:   *v = ((b1 == b2) && (b2 == b3));
417:   return(0);
418: }
419: */
420: /*
421: static PetscErrorCode _ComputeLocalCoordinateAffine2d(PetscReal xp[],PetscReal coords[],PetscReal xip[],PetscReal *dJ)
422: {
423:   PetscReal x1,y1,x2,y2,x3,y3;
424:   PetscReal c,b[2],A[2][2],inv[2][2],detJ,od;
425: 
427:   x1 = coords[2*0+0];
428:   x2 = coords[2*1+0];
429:   x3 = coords[2*2+0];
430: 
431:   y1 = coords[2*0+1];
432:   y2 = coords[2*1+1];
433:   y3 = coords[2*2+1];
434: 
435:   c = x1 - 0.5*x1 - 0.5*x1 + 0.5*x2 + 0.5*x3;
436:   b[0] = xp[0] - c;
437:   c = y1 - 0.5*y1 - 0.5*y1 + 0.5*y2 + 0.5*y3;
438:   b[1] = xp[1] - c;
439: 
440:   A[0][0] = -0.5*x1 + 0.5*x2;   A[0][1] = -0.5*x1 + 0.5*x3;
441:   A[1][0] = -0.5*y1 + 0.5*y2;   A[1][1] = -0.5*y1 + 0.5*y3;
442: 
443:   detJ = A[0][0]*A[1][1] - A[0][1]*A[1][0];
444:   *dJ = PetscAbsReal(detJ);
445:   od = 1.0/detJ;
446: 
447:   inv[0][0] =  A[1][1] * od;
448:   inv[0][1] = -A[0][1] * od;
449:   inv[1][0] = -A[1][0] * od;
450:   inv[1][1] =  A[0][0] * od;
451: 
452:   xip[0] = inv[0][0]*b[0] + inv[0][1]*b[1];
453:   xip[1] = inv[1][0]*b[0] + inv[1][1]*b[1];
454:   return(0);
455: }
456: */

458: static PetscErrorCode ComputeLocalCoordinateAffine2d(PetscReal xp[],PetscScalar coords[],PetscReal xip[],PetscReal *dJ)
459: {
460:   PetscReal x1,y1,x2,y2,x3,y3;
461:   PetscReal b[2],A[2][2],inv[2][2],detJ,od;
462: 
464:   x1 = PetscRealPart(coords[2*0+0]);
465:   x2 = PetscRealPart(coords[2*1+0]);
466:   x3 = PetscRealPart(coords[2*2+0]);
467: 
468:   y1 = PetscRealPart(coords[2*0+1]);
469:   y2 = PetscRealPart(coords[2*1+1]);
470:   y3 = PetscRealPart(coords[2*2+1]);
471: 
472:   b[0] = xp[0] - x1;
473:   b[1] = xp[1] - y1;
474: 
475:   A[0][0] = x2-x1;   A[0][1] = x3-x1;
476:   A[1][0] = y2-y1;   A[1][1] = y3-y1;
477: 
478:   detJ = A[0][0]*A[1][1] - A[0][1]*A[1][0];
479:   *dJ = PetscAbsReal(detJ);
480:   od = 1.0/detJ;
481: 
482:   inv[0][0] =  A[1][1] * od;
483:   inv[0][1] = -A[0][1] * od;
484:   inv[1][0] = -A[1][0] * od;
485:   inv[1][1] =  A[0][0] * od;
486: 
487:   xip[0] = inv[0][0]*b[0] + inv[0][1]*b[1];
488:   xip[1] = inv[1][0]*b[0] + inv[1][1]*b[1];
489:   return(0);
490: }

492: PetscErrorCode DMSwarmProjectField_ApproxP1_PLEX_2D(DM swarm,PetscReal *swarm_field,DM dm,Vec v_field)
493: {
495:   const PetscReal PLEX_C_EPS = 1.0e-8;
496:   Vec v_field_l,denom_l,coor_l,denom;
497:   PetscInt k,p,e,npoints;
498:   PetscInt *mpfield_cell;
499:   PetscReal *mpfield_coor;
500:   PetscReal xi_p[2];
501:   PetscScalar Ni[3];
502:   PetscSection coordSection;
503:   PetscScalar *elcoor = NULL;
504: 
506:   VecZeroEntries(v_field);
507: 
508:   DMGetLocalVector(dm,&v_field_l);
509:   DMGetGlobalVector(dm,&denom);
510:   DMGetLocalVector(dm,&denom_l);
511:   VecZeroEntries(v_field_l);
512:   VecZeroEntries(denom);
513:   VecZeroEntries(denom_l);
514: 
515:   DMGetCoordinatesLocal(dm,&coor_l);
516:   DMGetCoordinateSection(dm,&coordSection);
517: 
518:   DMSwarmGetLocalSize(swarm,&npoints);
519:   DMSwarmGetField(swarm,DMSwarmPICField_coor,NULL,NULL,(void**)&mpfield_coor);
520:   DMSwarmGetField(swarm,DMSwarmPICField_cellid,NULL,NULL,(void**)&mpfield_cell);
521: 
522:   for (p=0; p<npoints; p++) {
523:     PetscReal   *coor_p,dJ;
524:     PetscScalar elfield[3];
525:     PetscBool   point_located;
526: 
527:     e       = mpfield_cell[p];
528:     coor_p  = &mpfield_coor[2*p];
529: 
530:     DMPlexVecGetClosure(dm,coordSection,coor_l,e,NULL,&elcoor);

532: /*
533:     while (!point_located && (failed_counter < 25)) {
534:       PointInTriangle(point, coords[0], coords[1], coords[2], &point_located);
535:       point.x = coor_p[0];
536:       point.y = coor_p[1];
537:       point.x += 1.0e-10 * (2.0 * rand()/((double)RAND_MAX)-1.0);
538:       point.y += 1.0e-10 * (2.0 * rand()/((double)RAND_MAX)-1.0);
539:       failed_counter++;
540:     }

542:     if (!point_located){
543:         PetscPrintf(PETSC_COMM_SELF,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D) with triangle coords (%1.8e,%1.8e) : (%1.8e,%1.8e) : (%1.8e,%1.8e) in %D iterations\n",point.x,point.y,e,coords[0].x,coords[0].y,coords[1].x,coords[1].y,coords[2].x,coords[2].y,failed_counter);
544:     }
545:     
546:     if (!point_located) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D)\n",point.x,point.y,e);
547:     else {
548:       _ComputeLocalCoordinateAffine2d(coor_p,elcoor,xi_p,&dJ);
549:       xi_p[0] = 0.5*(xi_p[0] + 1.0);
550:       xi_p[1] = 0.5*(xi_p[1] + 1.0);
551:       
552:       PetscPrintf(PETSC_COMM_SELF,"[p=%D] x(%+1.4e,%+1.4e) -> mapped to element %D xi(%+1.4e,%+1.4e)\n",p,point.x,point.y,e,xi_p[0],xi_p[1]);
553:       
554:     }
555: */

557:     ComputeLocalCoordinateAffine2d(coor_p,elcoor,xi_p,&dJ);
558:     /*
559:     PetscPrintf(PETSC_COMM_SELF,"[p=%D] x(%+1.4e,%+1.4e) -> mapped to element %D xi(%+1.4e,%+1.4e)\n",p,point.x,point.y,e,xi_p[0],xi_p[1]);
560:     */
561:     /*
562:      point_located = PETSC_TRUE;
563:     if (xi_p[0] < 0.0) {
564:       if (xi_p[0] > -PLEX_C_EPS) {
565:         xi_p[0] = 0.0;
566:       } else {
567:         point_located = PETSC_FALSE;
568:       }
569:     }
570:     if (xi_p[1] < 0.0) {
571:       if (xi_p[1] > -PLEX_C_EPS) {
572:         xi_p[1] = 0.0;
573:       } else {
574:         point_located = PETSC_FALSE;
575:       }
576:     }
577:     if (xi_p[1] > (1.0-xi_p[0])) {
578:       if ((xi_p[1] - 1.0 + xi_p[0]) < PLEX_C_EPS) {
579:         xi_p[1] = 1.0 - xi_p[0];
580:       } else {
581:         point_located = PETSC_FALSE;
582:       }
583:     }
584:     if (!point_located){
585:       PetscPrintf(PETSC_COMM_SELF,"[Error] xi,eta = %+1.8e, %+1.8e\n",xi_p[0],xi_p[1]);
586:       PetscPrintf(PETSC_COMM_SELF,"[Error] Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D) with triangle coords (%1.8e,%1.8e) : (%1.8e,%1.8e) : (%1.8e,%1.8e)\n",coor_p[0],coor_p[1],e,elcoor[0],elcoor[1],elcoor[2],elcoor[3],elcoor[4],elcoor[5]);
587:     }
588:     if (!point_located) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D)\n",coor_p[0],coor_p[1],e);
589:     */

591:     Ni[0] = 1.0 - xi_p[0] - xi_p[1];
592:     Ni[1] = xi_p[0];
593:     Ni[2] = xi_p[1];

595:     point_located = PETSC_TRUE;
596:     for (k=0; k<3; k++) {
597:       if (PetscRealPart(Ni[k]) < -PLEX_C_EPS) point_located = PETSC_FALSE;
598:       if (PetscRealPart(Ni[k]) > (1.0+PLEX_C_EPS)) point_located = PETSC_FALSE;
599:     }
600:     if (!point_located){
601:       PetscPrintf(PETSC_COMM_SELF,"[Error] xi,eta = %+1.8e, %+1.8e\n",(double)xi_p[0],(double)xi_p[1]);
602:       PetscPrintf(PETSC_COMM_SELF,"[Error] Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D) with triangle coords (%1.8e,%1.8e) : (%1.8e,%1.8e) : (%1.8e,%1.8e)\n",(double)coor_p[0],(double)coor_p[1],e,(double)PetscRealPart(elcoor[0]),(double)PetscRealPart(elcoor[1]),(double)PetscRealPart(elcoor[2]),(double)PetscRealPart(elcoor[3]),(double)PetscRealPart(elcoor[4]),(double)PetscRealPart(elcoor[5]));
603:     }
604:     if (!point_located) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %D)\n",(double)coor_p[0],(double)coor_p[1],e);
605: 
606:     for (k=0; k<3; k++) {
607:       Ni[k] = Ni[k] * dJ;
608:       elfield[k] = Ni[k] * swarm_field[p];
609:     }
610: 
611:     DMPlexVecRestoreClosure(dm,coordSection,coor_l,e,NULL,&elcoor);

613:     DMPlexVecSetClosure(dm, NULL,v_field_l, e, elfield, ADD_VALUES);
614:     DMPlexVecSetClosure(dm, NULL,denom_l, e, Ni, ADD_VALUES);
615:   }
616: 
617:   DMSwarmRestoreField(swarm,DMSwarmPICField_cellid,NULL,NULL,(void**)&mpfield_cell);
618:   DMSwarmRestoreField(swarm,DMSwarmPICField_coor,NULL,NULL,(void**)&mpfield_coor);
619: 
620:   DMLocalToGlobalBegin(dm,v_field_l,ADD_VALUES,v_field);
621:   DMLocalToGlobalEnd(dm,v_field_l,ADD_VALUES,v_field);
622:   DMLocalToGlobalBegin(dm,denom_l,ADD_VALUES,denom);
623:   DMLocalToGlobalEnd(dm,denom_l,ADD_VALUES,denom);
624: 
625:   VecPointwiseDivide(v_field,v_field,denom);
626: 
627:   DMRestoreLocalVector(dm,&v_field_l);
628:   DMRestoreLocalVector(dm,&denom_l);
629:   DMRestoreGlobalVector(dm,&denom);
630: 
631:   return(0);
632: }

634: PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm,DM celldm,PetscInt project_type,PetscInt nfields,DMSwarmDataField dfield[],Vec vecs[])
635: {
637:   PetscInt f,dim;
638: 
640:   DMGetDimension(swarm,&dim);
641:   switch (dim) {
642:     case 2:
643:       for (f=0; f<nfields; f++) {
644:         PetscReal *swarm_field;
645: 
646:         DMSwarmDataFieldGetEntries(dfield[f],(void**)&swarm_field);
647:         DMSwarmProjectField_ApproxP1_PLEX_2D(swarm,swarm_field,celldm,vecs[f]);
648:       }
649:       break;
650:     case 3:
651:       SETERRQ(PetscObjectComm((PetscObject)swarm),PETSC_ERR_SUP,"No support for 3D");
652:       break;
653:     default:
654:       break;
655:   }
656: 
657:   return(0);
658: }

660: PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM dm,DM dmc,PetscInt npoints,PetscReal xi[])
661: {
662:   PetscBool is_simplex,is_tensorcell;
664:   PetscInt dim,nfaces,ps,pe,p,d,nbasis,pcnt,e,k,nel;
665:   PetscFE fe;
666:   PetscQuadrature quadrature;
667:   PetscReal *B,*xiq;
668:   Vec coorlocal;
669:   PetscSection coordSection;
670:   PetscScalar *elcoor = NULL;
671:   PetscReal *swarm_coor;
672:   PetscInt *swarm_cellid;
673: 
675:   DMGetDimension(dmc,&dim);
676: 
677:   is_simplex = PETSC_FALSE;
678:   is_tensorcell = PETSC_FALSE;
679:   DMPlexGetHeightStratum(dmc,0,&ps,&pe);
680:   DMPlexGetConeSize(dmc, ps, &nfaces);

682:   if (nfaces == (dim+1)) { is_simplex = PETSC_TRUE; }
683: 
684:   switch (dim) {
685:     case 2:
686:       if (nfaces == 4) { is_tensorcell = PETSC_TRUE; }
687:       break;
688:     case 3:
689:       if (nfaces == 6) { is_tensorcell = PETSC_TRUE; }
690:       break;
691:     default:
692:       SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only support for 2D, 3D");
693:       break;
694:   }

696:   /* check points provided fail inside the reference cell */
697:   if (is_simplex) {
698:     for (p=0; p<npoints; p++) {
699:       PetscReal sum;
700:       for (d=0; d<dim; d++) {
701:         if (xi[dim*p+d] < -1.0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Points do not fail inside the simplex domain");
702:       }
703:       sum = 0.0;
704:       for (d=0; d<dim; d++) {
705:         sum += xi[dim*p+d];
706:       }
707:       if (sum > 0.0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Points do not fail inside the simplex domain");
708:     }
709:   } else if (is_tensorcell) {
710:     for (p=0; p<npoints; p++) {
711:       for (d=0; d<dim; d++) {
712:         if (PetscAbsReal(xi[dim*p+d]) > 1.0) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Points do not fail inside the tensor domain [-1,1]^d");
713:       }
714:     }
715:   } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only support for d-simplex and d-tensorcell");

717:   PetscQuadratureCreate(PetscObjectComm((PetscObject)dm),&quadrature);
718:   PetscMalloc1(npoints*dim,&xiq);
719:   PetscMemcpy(xiq,xi,npoints*dim*sizeof(PetscReal));
720:   PetscQuadratureSetData(quadrature,dim,1,npoints,(const PetscReal*)xiq,NULL);
721:   private_PetscFECreateDefault_scalar_pk1(dmc, dim, is_simplex, 0, &fe);
722:   PetscFESetQuadrature(fe,quadrature);
723:   PetscFEGetDimension(fe,&nbasis);
724:   PetscFEGetDefaultTabulation(fe, &B, NULL, NULL);

726:   /* for each cell, interpolate coordaintes and insert the interpolated points coordinates into swarm */
727:   /* 0->cell, 1->edge, 2->vert */
728:   DMPlexGetHeightStratum(dmc,0,&ps,&pe);
729:   nel = pe - ps;
730: 
731:   DMSwarmSetLocalSizes(dm,npoints*nel,-1);
732:   DMSwarmGetField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
733:   DMSwarmGetField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
734: 
735:   DMGetCoordinatesLocal(dmc,&coorlocal);
736:   DMGetCoordinateSection(dmc,&coordSection);
737: 
738:   pcnt = 0;
739:   for (e=0; e<nel; e++) {
740:     DMPlexVecGetClosure(dmc,coordSection,coorlocal,ps+e,NULL,&elcoor);
741: 
742:     for (p=0; p<npoints; p++) {
743:       for (d=0; d<dim; d++) {
744:         swarm_coor[dim*pcnt+d] = 0.0;
745:         for (k=0; k<nbasis; k++) {
746:           swarm_coor[dim*pcnt+d] += B[p*nbasis + k] * PetscRealPart(elcoor[dim*k+d]);
747:         }
748:       }
749:       swarm_cellid[pcnt] = e;
750:       pcnt++;
751:     }
752:     DMPlexVecRestoreClosure(dmc,coordSection,coorlocal,ps+e,NULL,&elcoor);
753:   }
754:   DMSwarmRestoreField(dm,DMSwarmPICField_cellid,NULL,NULL,(void**)&swarm_cellid);
755:   DMSwarmRestoreField(dm,DMSwarmPICField_coor,NULL,NULL,(void**)&swarm_coor);
756: 
757:   PetscQuadratureDestroy(&quadrature);
758:   PetscFEDestroy(&fe);

760:   return(0);
761: }