xref: /petsc/src/dm/impls/swarm/swarmpic_plex.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
10e2ec84fSDave May #include <petscdm.h>
20e2ec84fSDave May #include <petscdmplex.h>
30e2ec84fSDave May #include <petscdmswarm.h>
4279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
50e2ec84fSDave May 
6b12d2206SDave May PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM, DM, PetscInt, PetscReal *xi);
7b12d2206SDave May 
8d71ae5a4SJacob Faibussowitsch static PetscErrorCode private_PetscFECreateDefault_scalar_pk1(DM dm, PetscInt dim, PetscBool isSimplex, PetscInt qorder, PetscFE *fem)
9d71ae5a4SJacob Faibussowitsch {
102cf64d79SDave May   const PetscInt  Nc = 1;
112cf64d79SDave May   PetscQuadrature q, fq;
122cf64d79SDave May   DM              K;
132cf64d79SDave May   PetscSpace      P;
142cf64d79SDave May   PetscDualSpace  Q;
152cf64d79SDave May   PetscInt        order, quadPointsPerEdge;
162cf64d79SDave May   PetscBool       tensor = isSimplex ? PETSC_FALSE : PETSC_TRUE;
172cf64d79SDave May 
182cf64d79SDave May   PetscFunctionBegin;
192cf64d79SDave May   /* Create space */
209566063dSJacob Faibussowitsch   PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)dm), &P));
219566063dSJacob Faibussowitsch   /* PetscCall(PetscObjectSetOptionsPrefix((PetscObject) P, prefix)); */
229566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialSetTensor(P, tensor));
239566063dSJacob Faibussowitsch   /* PetscCall(PetscSpaceSetFromOptions(P)); */
249566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL));
259566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetDegree(P, 1, PETSC_DETERMINE));
269566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumComponents(P, Nc));
279566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetNumVariables(P, dim));
289566063dSJacob Faibussowitsch   PetscCall(PetscSpaceSetUp(P));
299566063dSJacob Faibussowitsch   PetscCall(PetscSpaceGetDegree(P, &order, NULL));
309566063dSJacob Faibussowitsch   PetscCall(PetscSpacePolynomialGetTensor(P, &tensor));
312cf64d79SDave May   /* Create dual space */
329566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceCreate(PetscObjectComm((PetscObject)dm), &Q));
339566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE));
349566063dSJacob Faibussowitsch   /* PetscCall(PetscObjectSetOptionsPrefix((PetscObject) Q, prefix)); */
359566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K));
369566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetDM(Q, K));
379566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&K));
389566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetNumComponents(Q, Nc));
399566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetOrder(Q, order));
409566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceLagrangeSetTensor(Q, tensor));
419566063dSJacob Faibussowitsch   /* PetscCall(PetscDualSpaceSetFromOptions(Q)); */
429566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE));
439566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceSetUp(Q));
442cf64d79SDave May   /* Create element */
459566063dSJacob Faibussowitsch   PetscCall(PetscFECreate(PetscObjectComm((PetscObject)dm), fem));
469566063dSJacob Faibussowitsch   /* PetscCall(PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix)); */
479566063dSJacob Faibussowitsch   /* PetscCall(PetscFESetFromOptions(*fem)); */
489566063dSJacob Faibussowitsch   PetscCall(PetscFESetType(*fem, PETSCFEBASIC));
499566063dSJacob Faibussowitsch   PetscCall(PetscFESetBasisSpace(*fem, P));
509566063dSJacob Faibussowitsch   PetscCall(PetscFESetDualSpace(*fem, Q));
519566063dSJacob Faibussowitsch   PetscCall(PetscFESetNumComponents(*fem, Nc));
529566063dSJacob Faibussowitsch   PetscCall(PetscFESetUp(*fem));
539566063dSJacob Faibussowitsch   PetscCall(PetscSpaceDestroy(&P));
549566063dSJacob Faibussowitsch   PetscCall(PetscDualSpaceDestroy(&Q));
552cf64d79SDave May   /* Create quadrature (with specified order if given) */
562cf64d79SDave May   qorder            = qorder >= 0 ? qorder : order;
572cf64d79SDave May   quadPointsPerEdge = PetscMax(qorder + 1, 1);
582cf64d79SDave May   if (isSimplex) {
599566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q));
609566063dSJacob Faibussowitsch     PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, quadPointsPerEdge, -1.0, 1.0, &fq));
619371c9d4SSatish Balay   } else {
629566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim, 1, quadPointsPerEdge, -1.0, 1.0, &q));
639566063dSJacob Faibussowitsch     PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, quadPointsPerEdge, -1.0, 1.0, &fq));
642cf64d79SDave May   }
659566063dSJacob Faibussowitsch   PetscCall(PetscFESetQuadrature(*fem, q));
669566063dSJacob Faibussowitsch   PetscCall(PetscFESetFaceQuadrature(*fem, fq));
679566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&q));
689566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&fq));
69*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
702cf64d79SDave May }
712cf64d79SDave May 
72d71ae5a4SJacob Faibussowitsch PetscErrorCode subdivide_triangle(PetscReal v1[2], PetscReal v2[2], PetscReal v3[2], PetscInt depth, PetscInt max, PetscReal xi[], PetscInt *np)
73d71ae5a4SJacob Faibussowitsch {
740e2ec84fSDave May   PetscReal v12[2], v23[2], v31[2];
750e2ec84fSDave May   PetscInt  i;
760e2ec84fSDave May 
770e2ec84fSDave May   PetscFunctionBegin;
780e2ec84fSDave May   if (depth == max) {
790e2ec84fSDave May     PetscReal cx[2];
800e2ec84fSDave May 
810e2ec84fSDave May     cx[0] = (v1[0] + v2[0] + v3[0]) / 3.0;
820e2ec84fSDave May     cx[1] = (v1[1] + v2[1] + v3[1]) / 3.0;
830e2ec84fSDave May 
840e2ec84fSDave May     xi[2 * (*np) + 0] = cx[0];
850e2ec84fSDave May     xi[2 * (*np) + 1] = cx[1];
860e2ec84fSDave May     (*np)++;
87*3ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
880e2ec84fSDave May   }
890e2ec84fSDave May 
900e2ec84fSDave May   /* calculate midpoints of each side */
910e2ec84fSDave May   for (i = 0; i < 2; i++) {
920e2ec84fSDave May     v12[i] = (v1[i] + v2[i]) / 2.0;
930e2ec84fSDave May     v23[i] = (v2[i] + v3[i]) / 2.0;
940e2ec84fSDave May     v31[i] = (v3[i] + v1[i]) / 2.0;
950e2ec84fSDave May   }
960e2ec84fSDave May 
970e2ec84fSDave May   /* recursively subdivide new triangles */
989566063dSJacob Faibussowitsch   PetscCall(subdivide_triangle(v1, v12, v31, depth + 1, max, xi, np));
999566063dSJacob Faibussowitsch   PetscCall(subdivide_triangle(v2, v23, v12, depth + 1, max, xi, np));
1009566063dSJacob Faibussowitsch   PetscCall(subdivide_triangle(v3, v31, v23, depth + 1, max, xi, np));
1019566063dSJacob Faibussowitsch   PetscCall(subdivide_triangle(v12, v23, v31, depth + 1, max, xi, np));
102*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1030e2ec84fSDave May }
1040e2ec84fSDave May 
105d71ae5a4SJacob Faibussowitsch PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX2D_SubDivide(DM dm, DM dmc, PetscInt nsub)
106d71ae5a4SJacob Faibussowitsch {
1070e2ec84fSDave May   const PetscInt dim = 2;
1080e2ec84fSDave May   PetscInt       q, npoints_q, e, nel, npe, pcnt, ps, pe, d, k, depth;
1090e2ec84fSDave May   PetscReal     *xi;
1100e2ec84fSDave May   PetscReal    **basis;
1110e2ec84fSDave May   Vec            coorlocal;
1120e2ec84fSDave May   PetscSection   coordSection;
1130e2ec84fSDave May   PetscScalar   *elcoor = NULL;
1140e2ec84fSDave May   PetscReal     *swarm_coor;
1150e2ec84fSDave May   PetscInt      *swarm_cellid;
1160e2ec84fSDave May   PetscReal      v1[2], v2[2], v3[2];
1170e2ec84fSDave May 
1180e2ec84fSDave May   PetscFunctionBegin;
1190e2ec84fSDave May   npoints_q = 1;
120ad540459SPierre Jolivet   for (d = 0; d < nsub; d++) npoints_q *= 4;
1219566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dim * npoints_q, &xi));
1220e2ec84fSDave May 
1239371c9d4SSatish Balay   v1[0] = 0.0;
1249371c9d4SSatish Balay   v1[1] = 0.0;
1259371c9d4SSatish Balay   v2[0] = 1.0;
1269371c9d4SSatish Balay   v2[1] = 0.0;
1279371c9d4SSatish Balay   v3[0] = 0.0;
1289371c9d4SSatish Balay   v3[1] = 1.0;
1290e2ec84fSDave May   depth = 0;
1300e2ec84fSDave May   pcnt  = 0;
1319566063dSJacob Faibussowitsch   PetscCall(subdivide_triangle(v1, v2, v3, depth, nsub, xi, &pcnt));
1320e2ec84fSDave May 
1330e2ec84fSDave May   npe = 3; /* nodes per element (triangle) */
1349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(npoints_q, &basis));
1350e2ec84fSDave May   for (q = 0; q < npoints_q; q++) {
1369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(npe, &basis[q]));
1370e2ec84fSDave May 
1380e2ec84fSDave May     basis[q][0] = 1.0 - xi[dim * q + 0] - xi[dim * q + 1];
1390e2ec84fSDave May     basis[q][1] = xi[dim * q + 0];
1400e2ec84fSDave May     basis[q][2] = xi[dim * q + 1];
1410e2ec84fSDave May   }
1420e2ec84fSDave May 
1430e2ec84fSDave May   /* 0->cell, 1->edge, 2->vert */
1449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmc, 0, &ps, &pe));
1450e2ec84fSDave May   nel = pe - ps;
1460e2ec84fSDave May 
1479566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, npoints_q * nel, -1));
1489566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
1499566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
1500e2ec84fSDave May 
1519566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmc, &coorlocal));
1529566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmc, &coordSection));
1530e2ec84fSDave May 
1540e2ec84fSDave May   pcnt = 0;
1550e2ec84fSDave May   for (e = 0; e < nel; e++) {
1569566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmc, coordSection, coorlocal, e, NULL, &elcoor));
1570e2ec84fSDave May 
1580e2ec84fSDave May     for (q = 0; q < npoints_q; q++) {
1590e2ec84fSDave May       for (d = 0; d < dim; d++) {
1600e2ec84fSDave May         swarm_coor[dim * pcnt + d] = 0.0;
161ad540459SPierre Jolivet         for (k = 0; k < npe; k++) swarm_coor[dim * pcnt + d] += basis[q][k] * PetscRealPart(elcoor[dim * k + d]);
1620e2ec84fSDave May       }
1630e2ec84fSDave May       swarm_cellid[pcnt] = e;
1640e2ec84fSDave May       pcnt++;
1650e2ec84fSDave May     }
1669566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dmc, coordSection, coorlocal, e, NULL, &elcoor));
1670e2ec84fSDave May   }
1689566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
1699566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
1700e2ec84fSDave May 
1719566063dSJacob Faibussowitsch   PetscCall(PetscFree(xi));
17248a46eb9SPierre Jolivet   for (q = 0; q < npoints_q; q++) PetscCall(PetscFree(basis[q]));
1739566063dSJacob Faibussowitsch   PetscCall(PetscFree(basis));
174*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1750e2ec84fSDave May }
1760e2ec84fSDave May 
177d71ae5a4SJacob Faibussowitsch PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX_SubDivide(DM dm, DM dmc, PetscInt nsub)
178d71ae5a4SJacob Faibussowitsch {
17978185223SDave May   PetscInt         dim, nfaces, nbasis;
18078185223SDave May   PetscInt         q, npoints_q, e, nel, pcnt, ps, pe, d, k, r;
181ef0bb6c7SMatthew G. Knepley   PetscTabulation  T;
18278185223SDave May   Vec              coorlocal;
18378185223SDave May   PetscSection     coordSection;
18478185223SDave May   PetscScalar     *elcoor = NULL;
18578185223SDave May   PetscReal       *swarm_coor;
18678185223SDave May   PetscInt        *swarm_cellid;
18778185223SDave May   const PetscReal *xiq;
18878185223SDave May   PetscQuadrature  quadrature;
18978185223SDave May   PetscFE          fe, feRef;
19078185223SDave May   PetscBool        is_simplex;
19178185223SDave May 
19278185223SDave May   PetscFunctionBegin;
1939566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmc, &dim));
19478185223SDave May   is_simplex = PETSC_FALSE;
1959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmc, 0, &ps, &pe));
1969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dmc, ps, &nfaces));
197ad540459SPierre Jolivet   if (nfaces == (dim + 1)) is_simplex = PETSC_TRUE;
19878185223SDave May 
1999566063dSJacob Faibussowitsch   PetscCall(private_PetscFECreateDefault_scalar_pk1(dmc, dim, is_simplex, 0, &fe));
20078185223SDave May 
20178185223SDave May   for (r = 0; r < nsub; r++) {
2029566063dSJacob Faibussowitsch     PetscCall(PetscFERefine(fe, &feRef));
2039566063dSJacob Faibussowitsch     PetscCall(PetscFECopyQuadrature(feRef, fe));
2049566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&feRef));
20578185223SDave May   }
20678185223SDave May 
2079566063dSJacob Faibussowitsch   PetscCall(PetscFEGetQuadrature(fe, &quadrature));
2089566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureGetData(quadrature, NULL, NULL, &npoints_q, &xiq, NULL));
2099566063dSJacob Faibussowitsch   PetscCall(PetscFEGetDimension(fe, &nbasis));
2109566063dSJacob Faibussowitsch   PetscCall(PetscFEGetCellTabulation(fe, 1, &T));
21178185223SDave May 
21278185223SDave May   /* 0->cell, 1->edge, 2->vert */
2139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmc, 0, &ps, &pe));
21478185223SDave May   nel = pe - ps;
21578185223SDave May 
2169566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, npoints_q * nel, -1));
2179566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
2189566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
21978185223SDave May 
2209566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmc, &coorlocal));
2219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmc, &coordSection));
22278185223SDave May 
22378185223SDave May   pcnt = 0;
22478185223SDave May   for (e = 0; e < nel; e++) {
2259566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmc, coordSection, coorlocal, ps + e, NULL, &elcoor));
22678185223SDave May 
22778185223SDave May     for (q = 0; q < npoints_q; q++) {
22878185223SDave May       for (d = 0; d < dim; d++) {
22978185223SDave May         swarm_coor[dim * pcnt + d] = 0.0;
230ad540459SPierre Jolivet         for (k = 0; k < nbasis; k++) swarm_coor[dim * pcnt + d] += T->T[0][q * nbasis + k] * PetscRealPart(elcoor[dim * k + d]);
23178185223SDave May       }
23278185223SDave May       swarm_cellid[pcnt] = e;
23378185223SDave May       pcnt++;
23478185223SDave May     }
2359566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dmc, coordSection, coorlocal, ps + e, NULL, &elcoor));
23678185223SDave May   }
2379566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
2389566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
23978185223SDave May 
2409566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
241*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24278185223SDave May }
24378185223SDave May 
244d71ae5a4SJacob Faibussowitsch PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX2D_Regular(DM dm, DM dmc, PetscInt npoints)
245d71ae5a4SJacob Faibussowitsch {
246bc53056eSDave May   PetscInt     dim;
247bc53056eSDave May   PetscInt     ii, jj, q, npoints_q, e, nel, npe, pcnt, ps, pe, d, k, nfaces;
2480e2ec84fSDave May   PetscReal   *xi, ds, ds2;
2490e2ec84fSDave May   PetscReal  **basis;
2500e2ec84fSDave May   Vec          coorlocal;
2510e2ec84fSDave May   PetscSection coordSection;
2520e2ec84fSDave May   PetscScalar *elcoor = NULL;
2530e2ec84fSDave May   PetscReal   *swarm_coor;
2540e2ec84fSDave May   PetscInt    *swarm_cellid;
255bc53056eSDave May   PetscBool    is_simplex;
2560e2ec84fSDave May 
2570e2ec84fSDave May   PetscFunctionBegin;
2589566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmc, &dim));
25908401ef6SPierre Jolivet   PetscCheck(dim == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only 2D is supported");
260bc53056eSDave May   is_simplex = PETSC_FALSE;
2619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmc, 0, &ps, &pe));
2629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dmc, ps, &nfaces));
263ad540459SPierre Jolivet   if (nfaces == (dim + 1)) is_simplex = PETSC_TRUE;
26428b400f6SJacob Faibussowitsch   PetscCheck(is_simplex, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only the simplex is supported");
265bc53056eSDave May 
2669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dim * npoints * npoints, &xi));
2670e2ec84fSDave May   pcnt = 0;
2680e2ec84fSDave May   ds   = 1.0 / ((PetscReal)(npoints - 1));
2690e2ec84fSDave May   ds2  = 1.0 / ((PetscReal)(npoints));
2700e2ec84fSDave May   for (jj = 0; jj < npoints; jj++) {
2710e2ec84fSDave May     for (ii = 0; ii < npoints - jj; ii++) {
2720e2ec84fSDave May       xi[dim * pcnt + 0] = ii * ds;
2730e2ec84fSDave May       xi[dim * pcnt + 1] = jj * ds;
2740e2ec84fSDave May 
2750e2ec84fSDave May       xi[dim * pcnt + 0] *= (1.0 - 1.2 * ds2);
2760e2ec84fSDave May       xi[dim * pcnt + 1] *= (1.0 - 1.2 * ds2);
2770e2ec84fSDave May 
2780e2ec84fSDave May       xi[dim * pcnt + 0] += 0.35 * ds2;
2790e2ec84fSDave May       xi[dim * pcnt + 1] += 0.35 * ds2;
2800e2ec84fSDave May       pcnt++;
2810e2ec84fSDave May     }
2820e2ec84fSDave May   }
2830e2ec84fSDave May   npoints_q = pcnt;
2840e2ec84fSDave May 
2850e2ec84fSDave May   npe = 3; /* nodes per element (triangle) */
2869566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(npoints_q, &basis));
2870e2ec84fSDave May   for (q = 0; q < npoints_q; q++) {
2889566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(npe, &basis[q]));
2890e2ec84fSDave May 
2900e2ec84fSDave May     basis[q][0] = 1.0 - xi[dim * q + 0] - xi[dim * q + 1];
2910e2ec84fSDave May     basis[q][1] = xi[dim * q + 0];
2920e2ec84fSDave May     basis[q][2] = xi[dim * q + 1];
2930e2ec84fSDave May   }
2940e2ec84fSDave May 
2950e2ec84fSDave May   /* 0->cell, 1->edge, 2->vert */
2969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmc, 0, &ps, &pe));
2970e2ec84fSDave May   nel = pe - ps;
2980e2ec84fSDave May 
2999566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, npoints_q * nel, -1));
3009566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
3019566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
3020e2ec84fSDave May 
3039566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmc, &coorlocal));
3049566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmc, &coordSection));
3050e2ec84fSDave May 
3060e2ec84fSDave May   pcnt = 0;
3070e2ec84fSDave May   for (e = 0; e < nel; e++) {
3089566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmc, coordSection, coorlocal, e, NULL, &elcoor));
3090e2ec84fSDave May 
3100e2ec84fSDave May     for (q = 0; q < npoints_q; q++) {
3110e2ec84fSDave May       for (d = 0; d < dim; d++) {
3120e2ec84fSDave May         swarm_coor[dim * pcnt + d] = 0.0;
313ad540459SPierre Jolivet         for (k = 0; k < npe; k++) swarm_coor[dim * pcnt + d] += basis[q][k] * PetscRealPart(elcoor[dim * k + d]);
3140e2ec84fSDave May       }
3150e2ec84fSDave May       swarm_cellid[pcnt] = e;
3160e2ec84fSDave May       pcnt++;
3170e2ec84fSDave May     }
3189566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dmc, coordSection, coorlocal, e, NULL, &elcoor));
3190e2ec84fSDave May   }
3209566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
3219566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
3220e2ec84fSDave May 
3239566063dSJacob Faibussowitsch   PetscCall(PetscFree(xi));
32448a46eb9SPierre Jolivet   for (q = 0; q < npoints_q; q++) PetscCall(PetscFree(basis[q]));
3259566063dSJacob Faibussowitsch   PetscCall(PetscFree(basis));
326*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3270e2ec84fSDave May }
3280e2ec84fSDave May 
329d71ae5a4SJacob Faibussowitsch PetscErrorCode private_DMSwarmInsertPointsUsingCellDM_PLEX(DM dm, DM celldm, DMSwarmPICLayoutType layout, PetscInt layout_param)
330d71ae5a4SJacob Faibussowitsch {
3310e2ec84fSDave May   PetscInt dim;
3320e2ec84fSDave May 
3330e2ec84fSDave May   PetscFunctionBegin;
3349566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(celldm, &dim));
3350e2ec84fSDave May   switch (layout) {
3360e2ec84fSDave May   case DMSWARMPIC_LAYOUT_REGULAR:
33708401ef6SPierre Jolivet     PetscCheck(dim != 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No 3D support for REGULAR+PLEX");
3389566063dSJacob Faibussowitsch     PetscCall(private_DMSwarmInsertPointsUsingCellDM_PLEX2D_Regular(dm, celldm, layout_param));
3390e2ec84fSDave May     break;
3409371c9d4SSatish Balay   case DMSWARMPIC_LAYOUT_GAUSS: {
341b12d2206SDave May     PetscInt         npoints, npoints1, ps, pe, nfaces;
342b12d2206SDave May     const PetscReal *xi;
343b12d2206SDave May     PetscBool        is_simplex;
344b12d2206SDave May     PetscQuadrature  quadrature;
345b12d2206SDave May 
346b12d2206SDave May     is_simplex = PETSC_FALSE;
3479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(celldm, 0, &ps, &pe));
3489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(celldm, ps, &nfaces));
349ad540459SPierre Jolivet     if (nfaces == (dim + 1)) is_simplex = PETSC_TRUE;
350b12d2206SDave May 
351b12d2206SDave May     npoints1 = layout_param;
352b12d2206SDave May     if (is_simplex) {
3539566063dSJacob Faibussowitsch       PetscCall(PetscDTStroudConicalQuadrature(dim, 1, npoints1, -1.0, 1.0, &quadrature));
354b12d2206SDave May     } else {
3559566063dSJacob Faibussowitsch       PetscCall(PetscDTGaussTensorQuadrature(dim, 1, npoints1, -1.0, 1.0, &quadrature));
356b12d2206SDave May     }
3579566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureGetData(quadrature, NULL, NULL, &npoints, &xi, NULL));
3589566063dSJacob Faibussowitsch     PetscCall(private_DMSwarmSetPointCoordinatesCellwise_PLEX(dm, celldm, npoints, (PetscReal *)xi));
3599566063dSJacob Faibussowitsch     PetscCall(PetscQuadratureDestroy(&quadrature));
3609371c9d4SSatish Balay   } break;
361d71ae5a4SJacob Faibussowitsch   case DMSWARMPIC_LAYOUT_SUBDIVISION:
362d71ae5a4SJacob Faibussowitsch     PetscCall(private_DMSwarmInsertPointsUsingCellDM_PLEX_SubDivide(dm, celldm, layout_param));
363d71ae5a4SJacob Faibussowitsch     break;
3640e2ec84fSDave May   }
365*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3660e2ec84fSDave May }
367e3cd5995SDave May 
368e3cd5995SDave May /*
369e3cd5995SDave May typedef struct {
370e3cd5995SDave May   PetscReal x,y;
371e3cd5995SDave May } Point2d;
372e3cd5995SDave May 
373e3cd5995SDave May static PetscErrorCode signp2d(Point2d p1, Point2d p2, Point2d p3,PetscReal *s)
374e3cd5995SDave May {
375e3cd5995SDave May   PetscFunctionBegin;
376e3cd5995SDave May   *s = (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
377*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
378e3cd5995SDave May }
379e3cd5995SDave May */
380e3cd5995SDave May /*
381e3cd5995SDave May static PetscErrorCode PointInTriangle(Point2d pt, Point2d v1, Point2d v2, Point2d v3,PetscBool *v)
382e3cd5995SDave May {
383e3cd5995SDave May   PetscReal s1,s2,s3;
384e3cd5995SDave May   PetscBool b1, b2, b3;
385e3cd5995SDave May 
386e3cd5995SDave May   PetscFunctionBegin;
387e3cd5995SDave May   signp2d(pt, v1, v2,&s1); b1 = s1 < 0.0f;
388e3cd5995SDave May   signp2d(pt, v2, v3,&s2); b2 = s2 < 0.0f;
389e3cd5995SDave May   signp2d(pt, v3, v1,&s3); b3 = s3 < 0.0f;
390e3cd5995SDave May 
391e3cd5995SDave May   *v = ((b1 == b2) && (b2 == b3));
392*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
393e3cd5995SDave May }
394e3cd5995SDave May */
395e3cd5995SDave May /*
396e3cd5995SDave May static PetscErrorCode _ComputeLocalCoordinateAffine2d(PetscReal xp[],PetscReal coords[],PetscReal xip[],PetscReal *dJ)
397e3cd5995SDave May {
398e3cd5995SDave May   PetscReal x1,y1,x2,y2,x3,y3;
399e3cd5995SDave May   PetscReal c,b[2],A[2][2],inv[2][2],detJ,od;
400e3cd5995SDave May 
401e3cd5995SDave May   PetscFunctionBegin;
402e3cd5995SDave May   x1 = coords[2*0+0];
403e3cd5995SDave May   x2 = coords[2*1+0];
404e3cd5995SDave May   x3 = coords[2*2+0];
405e3cd5995SDave May 
406e3cd5995SDave May   y1 = coords[2*0+1];
407e3cd5995SDave May   y2 = coords[2*1+1];
408e3cd5995SDave May   y3 = coords[2*2+1];
409e3cd5995SDave May 
410e3cd5995SDave May   c = x1 - 0.5*x1 - 0.5*x1 + 0.5*x2 + 0.5*x3;
411e3cd5995SDave May   b[0] = xp[0] - c;
412e3cd5995SDave May   c = y1 - 0.5*y1 - 0.5*y1 + 0.5*y2 + 0.5*y3;
413e3cd5995SDave May   b[1] = xp[1] - c;
414e3cd5995SDave May 
415e3cd5995SDave May   A[0][0] = -0.5*x1 + 0.5*x2;   A[0][1] = -0.5*x1 + 0.5*x3;
416e3cd5995SDave May   A[1][0] = -0.5*y1 + 0.5*y2;   A[1][1] = -0.5*y1 + 0.5*y3;
417e3cd5995SDave May 
418e3cd5995SDave May   detJ = A[0][0]*A[1][1] - A[0][1]*A[1][0];
419e3cd5995SDave May   *dJ = PetscAbsReal(detJ);
420e3cd5995SDave May   od = 1.0/detJ;
421e3cd5995SDave May 
422e3cd5995SDave May   inv[0][0] =  A[1][1] * od;
423e3cd5995SDave May   inv[0][1] = -A[0][1] * od;
424e3cd5995SDave May   inv[1][0] = -A[1][0] * od;
425e3cd5995SDave May   inv[1][1] =  A[0][0] * od;
426e3cd5995SDave May 
427e3cd5995SDave May   xip[0] = inv[0][0]*b[0] + inv[0][1]*b[1];
428e3cd5995SDave May   xip[1] = inv[1][0]*b[0] + inv[1][1]*b[1];
429*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
430e3cd5995SDave May }
431e3cd5995SDave May */
432e3cd5995SDave May 
433d71ae5a4SJacob Faibussowitsch static PetscErrorCode ComputeLocalCoordinateAffine2d(PetscReal xp[], PetscScalar coords[], PetscReal xip[], PetscReal *dJ)
434d71ae5a4SJacob Faibussowitsch {
435e3cd5995SDave May   PetscReal x1, y1, x2, y2, x3, y3;
436e3cd5995SDave May   PetscReal b[2], A[2][2], inv[2][2], detJ, od;
437e3cd5995SDave May 
438e3cd5995SDave May   PetscFunctionBegin;
439a5f152d1SDave May   x1 = PetscRealPart(coords[2 * 0 + 0]);
440a5f152d1SDave May   x2 = PetscRealPart(coords[2 * 1 + 0]);
441a5f152d1SDave May   x3 = PetscRealPart(coords[2 * 2 + 0]);
442e3cd5995SDave May 
443a5f152d1SDave May   y1 = PetscRealPart(coords[2 * 0 + 1]);
444a5f152d1SDave May   y2 = PetscRealPart(coords[2 * 1 + 1]);
445a5f152d1SDave May   y3 = PetscRealPart(coords[2 * 2 + 1]);
446e3cd5995SDave May 
447e3cd5995SDave May   b[0] = xp[0] - x1;
448e3cd5995SDave May   b[1] = xp[1] - y1;
449e3cd5995SDave May 
4509371c9d4SSatish Balay   A[0][0] = x2 - x1;
4519371c9d4SSatish Balay   A[0][1] = x3 - x1;
4529371c9d4SSatish Balay   A[1][0] = y2 - y1;
4539371c9d4SSatish Balay   A[1][1] = y3 - y1;
454e3cd5995SDave May 
455e3cd5995SDave May   detJ = A[0][0] * A[1][1] - A[0][1] * A[1][0];
456e3cd5995SDave May   *dJ  = PetscAbsReal(detJ);
457e3cd5995SDave May   od   = 1.0 / detJ;
458e3cd5995SDave May 
459e3cd5995SDave May   inv[0][0] = A[1][1] * od;
460e3cd5995SDave May   inv[0][1] = -A[0][1] * od;
461e3cd5995SDave May   inv[1][0] = -A[1][0] * od;
462e3cd5995SDave May   inv[1][1] = A[0][0] * od;
463e3cd5995SDave May 
464e3cd5995SDave May   xip[0] = inv[0][0] * b[0] + inv[0][1] * b[1];
465e3cd5995SDave May   xip[1] = inv[1][0] * b[0] + inv[1][1] * b[1];
466*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
467e3cd5995SDave May }
468e3cd5995SDave May 
469d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmProjectField_ApproxP1_PLEX_2D(DM swarm, PetscReal *swarm_field, DM dm, Vec v_field)
470d71ae5a4SJacob Faibussowitsch {
471e3cd5995SDave May   const PetscReal PLEX_C_EPS = 1.0e-8;
472e3cd5995SDave May   Vec             v_field_l, denom_l, coor_l, denom;
473e3cd5995SDave May   PetscInt        k, p, e, npoints;
474e3cd5995SDave May   PetscInt       *mpfield_cell;
475e3cd5995SDave May   PetscReal      *mpfield_coor;
476a5f152d1SDave May   PetscReal       xi_p[2];
477a5f152d1SDave May   PetscScalar     Ni[3];
478e3cd5995SDave May   PetscSection    coordSection;
479e3cd5995SDave May   PetscScalar    *elcoor = NULL;
480e3cd5995SDave May 
481e3cd5995SDave May   PetscFunctionBegin;
4829566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(v_field));
483e3cd5995SDave May 
4849566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &v_field_l));
4859566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalVector(dm, &denom));
4869566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dm, &denom_l));
4879566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(v_field_l));
4889566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(denom));
4899566063dSJacob Faibussowitsch   PetscCall(VecZeroEntries(denom_l));
490e3cd5995SDave May 
4919566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coor_l));
4929566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
493e3cd5995SDave May 
4949566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetLocalSize(swarm, &npoints));
4959566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&mpfield_coor));
4969566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(swarm, DMSwarmPICField_cellid, NULL, NULL, (void **)&mpfield_cell));
497e3cd5995SDave May 
498e3cd5995SDave May   for (p = 0; p < npoints; p++) {
499a5f152d1SDave May     PetscReal  *coor_p, dJ;
500a5f152d1SDave May     PetscScalar elfield[3];
501e3cd5995SDave May     PetscBool   point_located;
502e3cd5995SDave May 
503e3cd5995SDave May     e      = mpfield_cell[p];
504e3cd5995SDave May     coor_p = &mpfield_coor[2 * p];
505e3cd5995SDave May 
5069566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dm, coordSection, coor_l, e, NULL, &elcoor));
507e3cd5995SDave May 
508e3cd5995SDave May     /*
509e3cd5995SDave May     while (!point_located && (failed_counter < 25)) {
5109566063dSJacob Faibussowitsch       PetscCall(PointInTriangle(point, coords[0], coords[1], coords[2], &point_located));
511e3cd5995SDave May       point.x = coor_p[0];
512e3cd5995SDave May       point.y = coor_p[1];
513e3cd5995SDave May       point.x += 1.0e-10 * (2.0 * rand()/((double)RAND_MAX)-1.0);
514e3cd5995SDave May       point.y += 1.0e-10 * (2.0 * rand()/((double)RAND_MAX)-1.0);
515e3cd5995SDave May       failed_counter++;
516e3cd5995SDave May     }
517e3cd5995SDave May 
518e3cd5995SDave May     if (!point_located) {
51963a3b9bcSJacob Faibussowitsch         PetscPrintf(PETSC_COMM_SELF,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %" PetscInt_FMT ") with triangle coords (%1.8e,%1.8e) : (%1.8e,%1.8e) : (%1.8e,%1.8e) in %" PetscInt_FMT " 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);
520e3cd5995SDave May     }
521e3cd5995SDave May 
52263a3b9bcSJacob Faibussowitsch     PetscCheck(point_located,PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %" PetscInt_FMT ")",point.x,point.y,e);
523e3cd5995SDave May     else {
5249566063dSJacob Faibussowitsch       PetscCall(_ComputeLocalCoordinateAffine2d(coor_p,elcoor,xi_p,&dJ));
525e3cd5995SDave May       xi_p[0] = 0.5*(xi_p[0] + 1.0);
526e3cd5995SDave May       xi_p[1] = 0.5*(xi_p[1] + 1.0);
527e3cd5995SDave May 
52863a3b9bcSJacob Faibussowitsch       PetscPrintf(PETSC_COMM_SELF,"[p=%" PetscInt_FMT "] x(%+1.4e,%+1.4e) -> mapped to element %" PetscInt_FMT " xi(%+1.4e,%+1.4e)\n",p,point.x,point.y,e,xi_p[0],xi_p[1]);
529e3cd5995SDave May 
530e3cd5995SDave May     }
531e3cd5995SDave May */
532e3cd5995SDave May 
5339566063dSJacob Faibussowitsch     PetscCall(ComputeLocalCoordinateAffine2d(coor_p, elcoor, xi_p, &dJ));
534e3cd5995SDave May     /*
53563a3b9bcSJacob Faibussowitsch     PetscPrintf(PETSC_COMM_SELF,"[p=%" PetscInt_FMT "] x(%+1.4e,%+1.4e) -> mapped to element %" PetscInt_FMT " xi(%+1.4e,%+1.4e)\n",p,point.x,point.y,e,xi_p[0],xi_p[1]);
536e3cd5995SDave May     */
537e3cd5995SDave May     /*
538e3cd5995SDave May      point_located = PETSC_TRUE;
539e3cd5995SDave May     if (xi_p[0] < 0.0) {
540e3cd5995SDave May       if (xi_p[0] > -PLEX_C_EPS) {
541e3cd5995SDave May         xi_p[0] = 0.0;
542e3cd5995SDave May       } else {
543e3cd5995SDave May         point_located = PETSC_FALSE;
544e3cd5995SDave May       }
545e3cd5995SDave May     }
546e3cd5995SDave May     if (xi_p[1] < 0.0) {
547e3cd5995SDave May       if (xi_p[1] > -PLEX_C_EPS) {
548e3cd5995SDave May         xi_p[1] = 0.0;
549e3cd5995SDave May       } else {
550e3cd5995SDave May         point_located = PETSC_FALSE;
551e3cd5995SDave May       }
552e3cd5995SDave May     }
553e3cd5995SDave May     if (xi_p[1] > (1.0-xi_p[0])) {
554e3cd5995SDave May       if ((xi_p[1] - 1.0 + xi_p[0]) < PLEX_C_EPS) {
555e3cd5995SDave May         xi_p[1] = 1.0 - xi_p[0];
556e3cd5995SDave May       } else {
557e3cd5995SDave May         point_located = PETSC_FALSE;
558e3cd5995SDave May       }
559e3cd5995SDave May     }
560e3cd5995SDave May     if (!point_located) {
561e3cd5995SDave May       PetscPrintf(PETSC_COMM_SELF,"[Error] xi,eta = %+1.8e, %+1.8e\n",xi_p[0],xi_p[1]);
56263a3b9bcSJacob Faibussowitsch       PetscPrintf(PETSC_COMM_SELF,"[Error] Failed to locate point (%1.8e,%1.8e) in local mesh (cell %" PetscInt_FMT ") 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]);
563e3cd5995SDave May     }
56463a3b9bcSJacob Faibussowitsch     PetscCheck(point_located,PETSC_COMM_SELF,PETSC_ERR_SUP,"Failed to locate point (%1.8e,%1.8e) in local mesh (cell %" PetscInt_FMT ")",coor_p[0],coor_p[1],e);
565e3cd5995SDave May     */
566e3cd5995SDave May 
567e3cd5995SDave May     Ni[0] = 1.0 - xi_p[0] - xi_p[1];
568e3cd5995SDave May     Ni[1] = xi_p[0];
569e3cd5995SDave May     Ni[2] = xi_p[1];
570e3cd5995SDave May 
571e3cd5995SDave May     point_located = PETSC_TRUE;
572e3cd5995SDave May     for (k = 0; k < 3; k++) {
573a5f152d1SDave May       if (PetscRealPart(Ni[k]) < -PLEX_C_EPS) point_located = PETSC_FALSE;
574a5f152d1SDave May       if (PetscRealPart(Ni[k]) > (1.0 + PLEX_C_EPS)) point_located = PETSC_FALSE;
575e3cd5995SDave May     }
576e3cd5995SDave May     if (!point_located) {
5779566063dSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "[Error] xi,eta = %+1.8e, %+1.8e\n", (double)xi_p[0], (double)xi_p[1]));
57863a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "[Error] Failed to locate point (%1.8e,%1.8e) in local mesh (cell %" PetscInt_FMT ") 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])));
579e3cd5995SDave May     }
58063a3b9bcSJacob Faibussowitsch     PetscCheck(point_located, PETSC_COMM_SELF, PETSC_ERR_SUP, "Failed to locate point (%1.8e,%1.8e) in local mesh (cell %" PetscInt_FMT ")", (double)coor_p[0], (double)coor_p[1], e);
581e3cd5995SDave May 
582e3cd5995SDave May     for (k = 0; k < 3; k++) {
583e3cd5995SDave May       Ni[k]      = Ni[k] * dJ;
584e3cd5995SDave May       elfield[k] = Ni[k] * swarm_field[p];
585e3cd5995SDave May     }
5869566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coor_l, e, NULL, &elcoor));
587e3cd5995SDave May 
5889566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure(dm, NULL, v_field_l, e, elfield, ADD_VALUES));
5899566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure(dm, NULL, denom_l, e, Ni, ADD_VALUES));
590e3cd5995SDave May   }
591e3cd5995SDave May 
5929566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(swarm, DMSwarmPICField_cellid, NULL, NULL, (void **)&mpfield_cell));
5939566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(swarm, DMSwarmPICField_coor, NULL, NULL, (void **)&mpfield_coor));
594e3cd5995SDave May 
5959566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, v_field_l, ADD_VALUES, v_field));
5969566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, v_field_l, ADD_VALUES, v_field));
5979566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dm, denom_l, ADD_VALUES, denom));
5989566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dm, denom_l, ADD_VALUES, denom));
599e3cd5995SDave May 
6009566063dSJacob Faibussowitsch   PetscCall(VecPointwiseDivide(v_field, v_field, denom));
601e3cd5995SDave May 
6029566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &v_field_l));
6039566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dm, &denom_l));
6049566063dSJacob Faibussowitsch   PetscCall(DMRestoreGlobalVector(dm, &denom));
605*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
606e3cd5995SDave May }
607e3cd5995SDave May 
608d71ae5a4SJacob Faibussowitsch PetscErrorCode private_DMSwarmProjectFields_PLEX(DM swarm, DM celldm, PetscInt project_type, PetscInt nfields, DMSwarmDataField dfield[], Vec vecs[])
609d71ae5a4SJacob Faibussowitsch {
610e3cd5995SDave May   PetscInt f, dim;
611e3cd5995SDave May 
612e3cd5995SDave May   PetscFunctionBegin;
6139566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(swarm, &dim));
614e3cd5995SDave May   switch (dim) {
615e3cd5995SDave May   case 2:
616e3cd5995SDave May     for (f = 0; f < nfields; f++) {
617e3cd5995SDave May       PetscReal *swarm_field;
618e3cd5995SDave May 
6199566063dSJacob Faibussowitsch       PetscCall(DMSwarmDataFieldGetEntries(dfield[f], (void **)&swarm_field));
6209566063dSJacob Faibussowitsch       PetscCall(DMSwarmProjectField_ApproxP1_PLEX_2D(swarm, swarm_field, celldm, vecs[f]));
621e3cd5995SDave May     }
622e3cd5995SDave May     break;
623d71ae5a4SJacob Faibussowitsch   case 3:
624d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)swarm), PETSC_ERR_SUP, "No support for 3D");
625d71ae5a4SJacob Faibussowitsch   default:
626d71ae5a4SJacob Faibussowitsch     break;
627e3cd5995SDave May   }
628*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629e3cd5995SDave May }
630431382f2SDave May 
631d71ae5a4SJacob Faibussowitsch PetscErrorCode private_DMSwarmSetPointCoordinatesCellwise_PLEX(DM dm, DM dmc, PetscInt npoints, PetscReal xi[])
632d71ae5a4SJacob Faibussowitsch {
633431382f2SDave May   PetscBool       is_simplex, is_tensorcell;
63492e40656SDave May   PetscInt        dim, nfaces, ps, pe, p, d, nbasis, pcnt, e, k, nel;
63592e40656SDave May   PetscFE         fe;
63692e40656SDave May   PetscQuadrature quadrature;
637ef0bb6c7SMatthew G. Knepley   PetscTabulation T;
638ef0bb6c7SMatthew G. Knepley   PetscReal      *xiq;
63992e40656SDave May   Vec             coorlocal;
64092e40656SDave May   PetscSection    coordSection;
64192e40656SDave May   PetscScalar    *elcoor = NULL;
64292e40656SDave May   PetscReal      *swarm_coor;
64392e40656SDave May   PetscInt       *swarm_cellid;
644431382f2SDave May 
64592e40656SDave May   PetscFunctionBegin;
6469566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmc, &dim));
647431382f2SDave May 
648431382f2SDave May   is_simplex    = PETSC_FALSE;
649431382f2SDave May   is_tensorcell = PETSC_FALSE;
6509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmc, 0, &ps, &pe));
6519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dmc, ps, &nfaces));
652431382f2SDave May 
653ad540459SPierre Jolivet   if (nfaces == (dim + 1)) is_simplex = PETSC_TRUE;
654431382f2SDave May 
655431382f2SDave May   switch (dim) {
656431382f2SDave May   case 2:
657ad540459SPierre Jolivet     if (nfaces == 4) is_tensorcell = PETSC_TRUE;
658431382f2SDave May     break;
659431382f2SDave May   case 3:
660ad540459SPierre Jolivet     if (nfaces == 6) is_tensorcell = PETSC_TRUE;
661431382f2SDave May     break;
662d71ae5a4SJacob Faibussowitsch   default:
663d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only support for 2D, 3D");
664431382f2SDave May   }
665431382f2SDave May 
66692e40656SDave May   /* check points provided fail inside the reference cell */
667431382f2SDave May   if (is_simplex) {
66892e40656SDave May     for (p = 0; p < npoints; p++) {
66992e40656SDave May       PetscReal sum;
670ad540459SPierre Jolivet       for (d = 0; d < dim; d++) PetscCheck(xi[dim * p + d] >= -1.0, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Points do not fail inside the simplex domain");
67192e40656SDave May       sum = 0.0;
672ad540459SPierre Jolivet       for (d = 0; d < dim; d++) sum += xi[dim * p + d];
67308401ef6SPierre Jolivet       PetscCheck(sum <= 0.0, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Points do not fail inside the simplex domain");
67492e40656SDave May     }
675431382f2SDave May   } else if (is_tensorcell) {
67692e40656SDave May     for (p = 0; p < npoints; p++) {
677ad540459SPierre Jolivet       for (d = 0; d < dim; d++) PetscCheck(PetscAbsReal(xi[dim * p + d]) <= 1.0, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Points do not fail inside the tensor domain [-1,1]^d");
67892e40656SDave May     }
679431382f2SDave May   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only support for d-simplex and d-tensorcell");
680431382f2SDave May 
6819566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureCreate(PetscObjectComm((PetscObject)dm), &quadrature));
6829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(npoints * dim, &xiq));
6839566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(xiq, xi, npoints * dim));
6849566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureSetData(quadrature, dim, 1, npoints, (const PetscReal *)xiq, NULL));
6859566063dSJacob Faibussowitsch   PetscCall(private_PetscFECreateDefault_scalar_pk1(dmc, dim, is_simplex, 0, &fe));
6869566063dSJacob Faibussowitsch   PetscCall(PetscFESetQuadrature(fe, quadrature));
6879566063dSJacob Faibussowitsch   PetscCall(PetscFEGetDimension(fe, &nbasis));
6889566063dSJacob Faibussowitsch   PetscCall(PetscFEGetCellTabulation(fe, 1, &T));
68992e40656SDave May 
69092e40656SDave May   /* for each cell, interpolate coordaintes and insert the interpolated points coordinates into swarm */
69192e40656SDave May   /* 0->cell, 1->edge, 2->vert */
6929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dmc, 0, &ps, &pe));
69392e40656SDave May   nel = pe - ps;
69492e40656SDave May 
6959566063dSJacob Faibussowitsch   PetscCall(DMSwarmSetLocalSizes(dm, npoints * nel, -1));
6969566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
6979566063dSJacob Faibussowitsch   PetscCall(DMSwarmGetField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
69892e40656SDave May 
6999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmc, &coorlocal));
7009566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dmc, &coordSection));
70192e40656SDave May 
70292e40656SDave May   pcnt = 0;
70392e40656SDave May   for (e = 0; e < nel; e++) {
7049566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure(dmc, coordSection, coorlocal, ps + e, NULL, &elcoor));
70592e40656SDave May 
70692e40656SDave May     for (p = 0; p < npoints; p++) {
70792e40656SDave May       for (d = 0; d < dim; d++) {
70892e40656SDave May         swarm_coor[dim * pcnt + d] = 0.0;
709ad540459SPierre Jolivet         for (k = 0; k < nbasis; k++) swarm_coor[dim * pcnt + d] += T->T[0][p * nbasis + k] * PetscRealPart(elcoor[dim * k + d]);
71092e40656SDave May       }
71192e40656SDave May       swarm_cellid[pcnt] = e;
71292e40656SDave May       pcnt++;
71392e40656SDave May     }
7149566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dmc, coordSection, coorlocal, ps + e, NULL, &elcoor));
71592e40656SDave May   }
7169566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_cellid, NULL, NULL, (void **)&swarm_cellid));
7179566063dSJacob Faibussowitsch   PetscCall(DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **)&swarm_coor));
71892e40656SDave May 
7199566063dSJacob Faibussowitsch   PetscCall(PetscQuadratureDestroy(&quadrature));
7209566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
721*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
722431382f2SDave May }
723