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