1*c6f61ee2SBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2*c6f61ee2SBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 3*c6f61ee2SBarry Smith #include <petscds.h> 4*c6f61ee2SBarry Smith #include <petsc/private/petscimpl.h> 5*c6f61ee2SBarry Smith #include <petsc/private/petscfeimpl.h> 6*c6f61ee2SBarry Smith 7*c6f61ee2SBarry Smith /*@C 8*c6f61ee2SBarry Smith DMInterpolationCreate - Creates a `DMInterpolationInfo` context 9*c6f61ee2SBarry Smith 10*c6f61ee2SBarry Smith Collective 11*c6f61ee2SBarry Smith 12*c6f61ee2SBarry Smith Input Parameter: 13*c6f61ee2SBarry Smith . comm - the communicator 14*c6f61ee2SBarry Smith 15*c6f61ee2SBarry Smith Output Parameter: 16*c6f61ee2SBarry Smith . ctx - the context 17*c6f61ee2SBarry Smith 18*c6f61ee2SBarry Smith Level: beginner 19*c6f61ee2SBarry Smith 20*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()`, `DMInterpolationDestroy()` 21*c6f61ee2SBarry Smith @*/ 22*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx) 23*c6f61ee2SBarry Smith { 24*c6f61ee2SBarry Smith PetscFunctionBegin; 25*c6f61ee2SBarry Smith PetscAssertPointer(ctx, 2); 26*c6f61ee2SBarry Smith PetscCall(PetscNew(ctx)); 27*c6f61ee2SBarry Smith 28*c6f61ee2SBarry Smith (*ctx)->comm = comm; 29*c6f61ee2SBarry Smith (*ctx)->dim = -1; 30*c6f61ee2SBarry Smith (*ctx)->nInput = 0; 31*c6f61ee2SBarry Smith (*ctx)->points = NULL; 32*c6f61ee2SBarry Smith (*ctx)->cells = NULL; 33*c6f61ee2SBarry Smith (*ctx)->n = -1; 34*c6f61ee2SBarry Smith (*ctx)->coords = NULL; 35*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 36*c6f61ee2SBarry Smith } 37*c6f61ee2SBarry Smith 38*c6f61ee2SBarry Smith /*@C 39*c6f61ee2SBarry Smith DMInterpolationSetDim - Sets the spatial dimension for the interpolation context 40*c6f61ee2SBarry Smith 41*c6f61ee2SBarry Smith Not Collective 42*c6f61ee2SBarry Smith 43*c6f61ee2SBarry Smith Input Parameters: 44*c6f61ee2SBarry Smith + ctx - the context 45*c6f61ee2SBarry Smith - dim - the spatial dimension 46*c6f61ee2SBarry Smith 47*c6f61ee2SBarry Smith Level: intermediate 48*c6f61ee2SBarry Smith 49*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationGetDim()`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()` 50*c6f61ee2SBarry Smith @*/ 51*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim) 52*c6f61ee2SBarry Smith { 53*c6f61ee2SBarry Smith PetscFunctionBegin; 54*c6f61ee2SBarry Smith PetscCheck(!(dim < 1) && !(dim > 3), ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %" PetscInt_FMT, dim); 55*c6f61ee2SBarry Smith ctx->dim = dim; 56*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 57*c6f61ee2SBarry Smith } 58*c6f61ee2SBarry Smith 59*c6f61ee2SBarry Smith /*@C 60*c6f61ee2SBarry Smith DMInterpolationGetDim - Gets the spatial dimension for the interpolation context 61*c6f61ee2SBarry Smith 62*c6f61ee2SBarry Smith Not Collective 63*c6f61ee2SBarry Smith 64*c6f61ee2SBarry Smith Input Parameter: 65*c6f61ee2SBarry Smith . ctx - the context 66*c6f61ee2SBarry Smith 67*c6f61ee2SBarry Smith Output Parameter: 68*c6f61ee2SBarry Smith . dim - the spatial dimension 69*c6f61ee2SBarry Smith 70*c6f61ee2SBarry Smith Level: intermediate 71*c6f61ee2SBarry Smith 72*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationSetDim()`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()` 73*c6f61ee2SBarry Smith @*/ 74*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim) 75*c6f61ee2SBarry Smith { 76*c6f61ee2SBarry Smith PetscFunctionBegin; 77*c6f61ee2SBarry Smith PetscAssertPointer(dim, 2); 78*c6f61ee2SBarry Smith *dim = ctx->dim; 79*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 80*c6f61ee2SBarry Smith } 81*c6f61ee2SBarry Smith 82*c6f61ee2SBarry Smith /*@C 83*c6f61ee2SBarry Smith DMInterpolationSetDof - Sets the number of fields interpolated at a point for the interpolation context 84*c6f61ee2SBarry Smith 85*c6f61ee2SBarry Smith Not Collective 86*c6f61ee2SBarry Smith 87*c6f61ee2SBarry Smith Input Parameters: 88*c6f61ee2SBarry Smith + ctx - the context 89*c6f61ee2SBarry Smith - dof - the number of fields 90*c6f61ee2SBarry Smith 91*c6f61ee2SBarry Smith Level: intermediate 92*c6f61ee2SBarry Smith 93*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationGetDof()`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()` 94*c6f61ee2SBarry Smith @*/ 95*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof) 96*c6f61ee2SBarry Smith { 97*c6f61ee2SBarry Smith PetscFunctionBegin; 98*c6f61ee2SBarry Smith PetscCheck(dof >= 1, ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %" PetscInt_FMT, dof); 99*c6f61ee2SBarry Smith ctx->dof = dof; 100*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 101*c6f61ee2SBarry Smith } 102*c6f61ee2SBarry Smith 103*c6f61ee2SBarry Smith /*@C 104*c6f61ee2SBarry Smith DMInterpolationGetDof - Gets the number of fields interpolated at a point for the interpolation context 105*c6f61ee2SBarry Smith 106*c6f61ee2SBarry Smith Not Collective 107*c6f61ee2SBarry Smith 108*c6f61ee2SBarry Smith Input Parameter: 109*c6f61ee2SBarry Smith . ctx - the context 110*c6f61ee2SBarry Smith 111*c6f61ee2SBarry Smith Output Parameter: 112*c6f61ee2SBarry Smith . dof - the number of fields 113*c6f61ee2SBarry Smith 114*c6f61ee2SBarry Smith Level: intermediate 115*c6f61ee2SBarry Smith 116*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationSetDof()`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()` 117*c6f61ee2SBarry Smith @*/ 118*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof) 119*c6f61ee2SBarry Smith { 120*c6f61ee2SBarry Smith PetscFunctionBegin; 121*c6f61ee2SBarry Smith PetscAssertPointer(dof, 2); 122*c6f61ee2SBarry Smith *dof = ctx->dof; 123*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 124*c6f61ee2SBarry Smith } 125*c6f61ee2SBarry Smith 126*c6f61ee2SBarry Smith /*@C 127*c6f61ee2SBarry Smith DMInterpolationAddPoints - Add points at which we will interpolate the fields 128*c6f61ee2SBarry Smith 129*c6f61ee2SBarry Smith Not Collective 130*c6f61ee2SBarry Smith 131*c6f61ee2SBarry Smith Input Parameters: 132*c6f61ee2SBarry Smith + ctx - the context 133*c6f61ee2SBarry Smith . n - the number of points 134*c6f61ee2SBarry Smith - points - the coordinates for each point, an array of size n * dim 135*c6f61ee2SBarry Smith 136*c6f61ee2SBarry Smith Level: intermediate 137*c6f61ee2SBarry Smith 138*c6f61ee2SBarry Smith Note: 139*c6f61ee2SBarry Smith The coordinate information is copied. 140*c6f61ee2SBarry Smith 141*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationSetDim()`, `DMInterpolationEvaluate()`, `DMInterpolationCreate()` 142*c6f61ee2SBarry Smith @*/ 143*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[]) 144*c6f61ee2SBarry Smith { 145*c6f61ee2SBarry Smith PetscFunctionBegin; 146*c6f61ee2SBarry Smith PetscCheck(ctx->dim >= 0, ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 147*c6f61ee2SBarry Smith PetscCheck(!ctx->points, ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet"); 148*c6f61ee2SBarry Smith ctx->nInput = n; 149*c6f61ee2SBarry Smith 150*c6f61ee2SBarry Smith PetscCall(PetscMalloc1(n * ctx->dim, &ctx->points)); 151*c6f61ee2SBarry Smith PetscCall(PetscArraycpy(ctx->points, points, n * ctx->dim)); 152*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 153*c6f61ee2SBarry Smith } 154*c6f61ee2SBarry Smith 155*c6f61ee2SBarry Smith /*@C 156*c6f61ee2SBarry Smith DMInterpolationSetUp - Compute spatial indices for point location during interpolation 157*c6f61ee2SBarry Smith 158*c6f61ee2SBarry Smith Collective 159*c6f61ee2SBarry Smith 160*c6f61ee2SBarry Smith Input Parameters: 161*c6f61ee2SBarry Smith + ctx - the context 162*c6f61ee2SBarry Smith . dm - the `DM` for the function space used for interpolation 163*c6f61ee2SBarry Smith . redundantPoints - If `PETSC_TRUE`, all processes are passing in the same array of points. Otherwise, points need to be communicated among processes. 164*c6f61ee2SBarry Smith - ignoreOutsideDomain - If `PETSC_TRUE`, ignore points outside the domain, otherwise return an error 165*c6f61ee2SBarry Smith 166*c6f61ee2SBarry Smith Level: intermediate 167*c6f61ee2SBarry Smith 168*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()`, `DMInterpolationCreate()` 169*c6f61ee2SBarry Smith @*/ 170*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints, PetscBool ignoreOutsideDomain) 171*c6f61ee2SBarry Smith { 172*c6f61ee2SBarry Smith MPI_Comm comm = ctx->comm; 173*c6f61ee2SBarry Smith PetscScalar *a; 174*c6f61ee2SBarry Smith PetscInt p, q, i; 175*c6f61ee2SBarry Smith PetscMPIInt rank, size; 176*c6f61ee2SBarry Smith Vec pointVec; 177*c6f61ee2SBarry Smith PetscSF cellSF; 178*c6f61ee2SBarry Smith PetscLayout layout; 179*c6f61ee2SBarry Smith PetscReal *globalPoints; 180*c6f61ee2SBarry Smith PetscScalar *globalPointsScalar; 181*c6f61ee2SBarry Smith const PetscInt *ranges; 182*c6f61ee2SBarry Smith PetscMPIInt *counts, *displs; 183*c6f61ee2SBarry Smith const PetscSFNode *foundCells; 184*c6f61ee2SBarry Smith const PetscInt *foundPoints; 185*c6f61ee2SBarry Smith PetscMPIInt *foundProcs, *globalProcs; 186*c6f61ee2SBarry Smith PetscInt n, N, numFound; 187*c6f61ee2SBarry Smith 188*c6f61ee2SBarry Smith PetscFunctionBegin; 189*c6f61ee2SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 190*c6f61ee2SBarry Smith PetscCallMPI(MPI_Comm_size(comm, &size)); 191*c6f61ee2SBarry Smith PetscCallMPI(MPI_Comm_rank(comm, &rank)); 192*c6f61ee2SBarry Smith PetscCheck(ctx->dim >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 193*c6f61ee2SBarry Smith /* Locate points */ 194*c6f61ee2SBarry Smith n = ctx->nInput; 195*c6f61ee2SBarry Smith if (!redundantPoints) { 196*c6f61ee2SBarry Smith PetscCall(PetscLayoutCreate(comm, &layout)); 197*c6f61ee2SBarry Smith PetscCall(PetscLayoutSetBlockSize(layout, 1)); 198*c6f61ee2SBarry Smith PetscCall(PetscLayoutSetLocalSize(layout, n)); 199*c6f61ee2SBarry Smith PetscCall(PetscLayoutSetUp(layout)); 200*c6f61ee2SBarry Smith PetscCall(PetscLayoutGetSize(layout, &N)); 201*c6f61ee2SBarry Smith /* Communicate all points to all processes */ 202*c6f61ee2SBarry Smith PetscCall(PetscMalloc3(N * ctx->dim, &globalPoints, size, &counts, size, &displs)); 203*c6f61ee2SBarry Smith PetscCall(PetscLayoutGetRanges(layout, &ranges)); 204*c6f61ee2SBarry Smith for (p = 0; p < size; ++p) { 205*c6f61ee2SBarry Smith counts[p] = (ranges[p + 1] - ranges[p]) * ctx->dim; 206*c6f61ee2SBarry Smith displs[p] = ranges[p] * ctx->dim; 207*c6f61ee2SBarry Smith } 208*c6f61ee2SBarry Smith PetscCallMPI(MPI_Allgatherv(ctx->points, n * ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm)); 209*c6f61ee2SBarry Smith } else { 210*c6f61ee2SBarry Smith N = n; 211*c6f61ee2SBarry Smith globalPoints = ctx->points; 212*c6f61ee2SBarry Smith counts = displs = NULL; 213*c6f61ee2SBarry Smith layout = NULL; 214*c6f61ee2SBarry Smith } 215*c6f61ee2SBarry Smith #if 0 216*c6f61ee2SBarry Smith PetscCall(PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs)); 217*c6f61ee2SBarry Smith /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */ 218*c6f61ee2SBarry Smith #else 219*c6f61ee2SBarry Smith #if defined(PETSC_USE_COMPLEX) 220*c6f61ee2SBarry Smith PetscCall(PetscMalloc1(N * ctx->dim, &globalPointsScalar)); 221*c6f61ee2SBarry Smith for (i = 0; i < N * ctx->dim; i++) globalPointsScalar[i] = globalPoints[i]; 222*c6f61ee2SBarry Smith #else 223*c6f61ee2SBarry Smith globalPointsScalar = globalPoints; 224*c6f61ee2SBarry Smith #endif 225*c6f61ee2SBarry Smith PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N * ctx->dim, globalPointsScalar, &pointVec)); 226*c6f61ee2SBarry Smith PetscCall(PetscMalloc2(N, &foundProcs, N, &globalProcs)); 227*c6f61ee2SBarry Smith for (p = 0; p < N; ++p) foundProcs[p] = size; 228*c6f61ee2SBarry Smith cellSF = NULL; 229*c6f61ee2SBarry Smith PetscCall(DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF)); 230*c6f61ee2SBarry Smith PetscCall(PetscSFGetGraph(cellSF, NULL, &numFound, &foundPoints, &foundCells)); 231*c6f61ee2SBarry Smith #endif 232*c6f61ee2SBarry Smith for (p = 0; p < numFound; ++p) { 233*c6f61ee2SBarry Smith if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank; 234*c6f61ee2SBarry Smith } 235*c6f61ee2SBarry Smith /* Let the lowest rank process own each point */ 236*c6f61ee2SBarry Smith PetscCall(MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm)); 237*c6f61ee2SBarry Smith ctx->n = 0; 238*c6f61ee2SBarry Smith for (p = 0; p < N; ++p) { 239*c6f61ee2SBarry Smith if (globalProcs[p] == size) { 240*c6f61ee2SBarry Smith PetscCheck(ignoreOutsideDomain, comm, PETSC_ERR_PLIB, "Point %" PetscInt_FMT ": %g %g %g not located in mesh", p, (double)globalPoints[p * ctx->dim + 0], (double)(ctx->dim > 1 ? globalPoints[p * ctx->dim + 1] : 0.0), 241*c6f61ee2SBarry Smith (double)(ctx->dim > 2 ? globalPoints[p * ctx->dim + 2] : 0.0)); 242*c6f61ee2SBarry Smith if (rank == 0) ++ctx->n; 243*c6f61ee2SBarry Smith } else if (globalProcs[p] == rank) ++ctx->n; 244*c6f61ee2SBarry Smith } 245*c6f61ee2SBarry Smith /* Create coordinates vector and array of owned cells */ 246*c6f61ee2SBarry Smith PetscCall(PetscMalloc1(ctx->n, &ctx->cells)); 247*c6f61ee2SBarry Smith PetscCall(VecCreate(comm, &ctx->coords)); 248*c6f61ee2SBarry Smith PetscCall(VecSetSizes(ctx->coords, ctx->n * ctx->dim, PETSC_DECIDE)); 249*c6f61ee2SBarry Smith PetscCall(VecSetBlockSize(ctx->coords, ctx->dim)); 250*c6f61ee2SBarry Smith PetscCall(VecSetType(ctx->coords, VECSTANDARD)); 251*c6f61ee2SBarry Smith PetscCall(VecGetArray(ctx->coords, &a)); 252*c6f61ee2SBarry Smith for (p = 0, q = 0, i = 0; p < N; ++p) { 253*c6f61ee2SBarry Smith if (globalProcs[p] == rank) { 254*c6f61ee2SBarry Smith PetscInt d; 255*c6f61ee2SBarry Smith 256*c6f61ee2SBarry Smith for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p * ctx->dim + d]; 257*c6f61ee2SBarry Smith ctx->cells[q] = foundCells[q].index; 258*c6f61ee2SBarry Smith ++q; 259*c6f61ee2SBarry Smith } 260*c6f61ee2SBarry Smith if (globalProcs[p] == size && rank == 0) { 261*c6f61ee2SBarry Smith PetscInt d; 262*c6f61ee2SBarry Smith 263*c6f61ee2SBarry Smith for (d = 0; d < ctx->dim; ++d, ++i) a[i] = 0.; 264*c6f61ee2SBarry Smith ctx->cells[q] = -1; 265*c6f61ee2SBarry Smith ++q; 266*c6f61ee2SBarry Smith } 267*c6f61ee2SBarry Smith } 268*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(ctx->coords, &a)); 269*c6f61ee2SBarry Smith #if 0 270*c6f61ee2SBarry Smith PetscCall(PetscFree3(foundCells,foundProcs,globalProcs)); 271*c6f61ee2SBarry Smith #else 272*c6f61ee2SBarry Smith PetscCall(PetscFree2(foundProcs, globalProcs)); 273*c6f61ee2SBarry Smith PetscCall(PetscSFDestroy(&cellSF)); 274*c6f61ee2SBarry Smith PetscCall(VecDestroy(&pointVec)); 275*c6f61ee2SBarry Smith #endif 276*c6f61ee2SBarry Smith if ((void *)globalPointsScalar != (void *)globalPoints) PetscCall(PetscFree(globalPointsScalar)); 277*c6f61ee2SBarry Smith if (!redundantPoints) PetscCall(PetscFree3(globalPoints, counts, displs)); 278*c6f61ee2SBarry Smith PetscCall(PetscLayoutDestroy(&layout)); 279*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 280*c6f61ee2SBarry Smith } 281*c6f61ee2SBarry Smith 282*c6f61ee2SBarry Smith /*@C 283*c6f61ee2SBarry Smith DMInterpolationGetCoordinates - Gets a `Vec` with the coordinates of each interpolation point 284*c6f61ee2SBarry Smith 285*c6f61ee2SBarry Smith Collective 286*c6f61ee2SBarry Smith 287*c6f61ee2SBarry Smith Input Parameter: 288*c6f61ee2SBarry Smith . ctx - the context 289*c6f61ee2SBarry Smith 290*c6f61ee2SBarry Smith Output Parameter: 291*c6f61ee2SBarry Smith . coordinates - the coordinates of interpolation points 292*c6f61ee2SBarry Smith 293*c6f61ee2SBarry Smith Level: intermediate 294*c6f61ee2SBarry Smith 295*c6f61ee2SBarry Smith Note: 296*c6f61ee2SBarry Smith The local vector entries correspond to interpolation points lying on this process, according to the associated `DM`. 297*c6f61ee2SBarry Smith This is a borrowed vector that the user should not destroy. 298*c6f61ee2SBarry Smith 299*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()`, `DMInterpolationCreate()` 300*c6f61ee2SBarry Smith @*/ 301*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates) 302*c6f61ee2SBarry Smith { 303*c6f61ee2SBarry Smith PetscFunctionBegin; 304*c6f61ee2SBarry Smith PetscAssertPointer(coordinates, 2); 305*c6f61ee2SBarry Smith PetscCheck(ctx->coords, ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 306*c6f61ee2SBarry Smith *coordinates = ctx->coords; 307*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 308*c6f61ee2SBarry Smith } 309*c6f61ee2SBarry Smith 310*c6f61ee2SBarry Smith /*@C 311*c6f61ee2SBarry Smith DMInterpolationGetVector - Gets a `Vec` which can hold all the interpolated field values 312*c6f61ee2SBarry Smith 313*c6f61ee2SBarry Smith Collective 314*c6f61ee2SBarry Smith 315*c6f61ee2SBarry Smith Input Parameter: 316*c6f61ee2SBarry Smith . ctx - the context 317*c6f61ee2SBarry Smith 318*c6f61ee2SBarry Smith Output Parameter: 319*c6f61ee2SBarry Smith . v - a vector capable of holding the interpolated field values 320*c6f61ee2SBarry Smith 321*c6f61ee2SBarry Smith Level: intermediate 322*c6f61ee2SBarry Smith 323*c6f61ee2SBarry Smith Note: 324*c6f61ee2SBarry Smith This vector should be returned using `DMInterpolationRestoreVector()`. 325*c6f61ee2SBarry Smith 326*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationRestoreVector()`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()`, `DMInterpolationCreate()` 327*c6f61ee2SBarry Smith @*/ 328*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v) 329*c6f61ee2SBarry Smith { 330*c6f61ee2SBarry Smith PetscFunctionBegin; 331*c6f61ee2SBarry Smith PetscAssertPointer(v, 2); 332*c6f61ee2SBarry Smith PetscCheck(ctx->coords, ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 333*c6f61ee2SBarry Smith PetscCall(VecCreate(ctx->comm, v)); 334*c6f61ee2SBarry Smith PetscCall(VecSetSizes(*v, ctx->n * ctx->dof, PETSC_DECIDE)); 335*c6f61ee2SBarry Smith PetscCall(VecSetBlockSize(*v, ctx->dof)); 336*c6f61ee2SBarry Smith PetscCall(VecSetType(*v, VECSTANDARD)); 337*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 338*c6f61ee2SBarry Smith } 339*c6f61ee2SBarry Smith 340*c6f61ee2SBarry Smith /*@C 341*c6f61ee2SBarry Smith DMInterpolationRestoreVector - Returns a `Vec` which can hold all the interpolated field values 342*c6f61ee2SBarry Smith 343*c6f61ee2SBarry Smith Collective 344*c6f61ee2SBarry Smith 345*c6f61ee2SBarry Smith Input Parameters: 346*c6f61ee2SBarry Smith + ctx - the context 347*c6f61ee2SBarry Smith - v - a vector capable of holding the interpolated field values 348*c6f61ee2SBarry Smith 349*c6f61ee2SBarry Smith Level: intermediate 350*c6f61ee2SBarry Smith 351*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationGetVector()`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()`, `DMInterpolationCreate()` 352*c6f61ee2SBarry Smith @*/ 353*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v) 354*c6f61ee2SBarry Smith { 355*c6f61ee2SBarry Smith PetscFunctionBegin; 356*c6f61ee2SBarry Smith PetscAssertPointer(v, 2); 357*c6f61ee2SBarry Smith PetscCheck(ctx->coords, ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 358*c6f61ee2SBarry Smith PetscCall(VecDestroy(v)); 359*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 360*c6f61ee2SBarry Smith } 361*c6f61ee2SBarry Smith 362*c6f61ee2SBarry Smith static inline PetscErrorCode DMInterpolate_Segment_Private(DMInterpolationInfo ctx, DM dm, PetscInt p, Vec xLocal, Vec v) 363*c6f61ee2SBarry Smith { 364*c6f61ee2SBarry Smith const PetscInt c = ctx->cells[p]; 365*c6f61ee2SBarry Smith const PetscInt dof = ctx->dof; 366*c6f61ee2SBarry Smith PetscScalar *x = NULL; 367*c6f61ee2SBarry Smith const PetscScalar *coords; 368*c6f61ee2SBarry Smith PetscScalar *a; 369*c6f61ee2SBarry Smith PetscReal v0, J, invJ, detJ, xir[1]; 370*c6f61ee2SBarry Smith PetscInt xSize, comp; 371*c6f61ee2SBarry Smith 372*c6f61ee2SBarry Smith PetscFunctionBegin; 373*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(ctx->coords, &coords)); 374*c6f61ee2SBarry Smith PetscCall(VecGetArray(v, &a)); 375*c6f61ee2SBarry Smith PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0, &J, &invJ, &detJ)); 376*c6f61ee2SBarry Smith PetscCheck(detJ > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT, (double)detJ, c); 377*c6f61ee2SBarry Smith xir[0] = invJ * PetscRealPart(coords[p] - v0); 378*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x)); 379*c6f61ee2SBarry Smith if (2 * dof == xSize) { 380*c6f61ee2SBarry Smith for (comp = 0; comp < dof; ++comp) a[p * dof + comp] = x[0 * dof + comp] * (1 - xir[0]) + x[1 * dof + comp] * xir[0]; 381*c6f61ee2SBarry Smith } else if (dof == xSize) { 382*c6f61ee2SBarry Smith for (comp = 0; comp < dof; ++comp) a[p * dof + comp] = x[0 * dof + comp]; 383*c6f61ee2SBarry Smith } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input closure size %" PetscInt_FMT " must be either %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 2 * dof, dof); 384*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x)); 385*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(v, &a)); 386*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(ctx->coords, &coords)); 387*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 388*c6f61ee2SBarry Smith } 389*c6f61ee2SBarry Smith 390*c6f61ee2SBarry Smith static inline PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, PetscInt p, Vec xLocal, Vec v) 391*c6f61ee2SBarry Smith { 392*c6f61ee2SBarry Smith const PetscInt c = ctx->cells[p]; 393*c6f61ee2SBarry Smith PetscScalar *x = NULL; 394*c6f61ee2SBarry Smith const PetscScalar *coords; 395*c6f61ee2SBarry Smith PetscScalar *a; 396*c6f61ee2SBarry Smith PetscReal *v0, *J, *invJ, detJ; 397*c6f61ee2SBarry Smith PetscReal xi[4]; 398*c6f61ee2SBarry Smith 399*c6f61ee2SBarry Smith PetscFunctionBegin; 400*c6f61ee2SBarry Smith PetscCall(PetscMalloc3(ctx->dim, &v0, ctx->dim * ctx->dim, &J, ctx->dim * ctx->dim, &invJ)); 401*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(ctx->coords, &coords)); 402*c6f61ee2SBarry Smith PetscCall(VecGetArray(v, &a)); 403*c6f61ee2SBarry Smith PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); 404*c6f61ee2SBarry Smith PetscCheck(detJ > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT, (double)detJ, c); 405*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x)); 406*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < ctx->dof; ++comp) a[p * ctx->dof + comp] = x[0 * ctx->dof + comp]; 407*c6f61ee2SBarry Smith for (PetscInt d = 0; d < ctx->dim; ++d) { 408*c6f61ee2SBarry Smith xi[d] = 0.0; 409*c6f61ee2SBarry Smith for (PetscInt f = 0; f < ctx->dim; ++f) xi[d] += invJ[d * ctx->dim + f] * 0.5 * PetscRealPart(coords[p * ctx->dim + f] - v0[f]); 410*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < ctx->dof; ++comp) a[p * ctx->dof + comp] += PetscRealPart(x[(d + 1) * ctx->dof + comp] - x[0 * ctx->dof + comp]) * xi[d]; 411*c6f61ee2SBarry Smith } 412*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x)); 413*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(v, &a)); 414*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(ctx->coords, &coords)); 415*c6f61ee2SBarry Smith PetscCall(PetscFree3(v0, J, invJ)); 416*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 417*c6f61ee2SBarry Smith } 418*c6f61ee2SBarry Smith 419*c6f61ee2SBarry Smith static inline PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, PetscInt p, Vec xLocal, Vec v) 420*c6f61ee2SBarry Smith { 421*c6f61ee2SBarry Smith const PetscInt c = ctx->cells[p]; 422*c6f61ee2SBarry Smith const PetscInt order[3] = {2, 1, 3}; 423*c6f61ee2SBarry Smith PetscScalar *x = NULL; 424*c6f61ee2SBarry Smith PetscReal *v0, *J, *invJ, detJ; 425*c6f61ee2SBarry Smith const PetscScalar *coords; 426*c6f61ee2SBarry Smith PetscScalar *a; 427*c6f61ee2SBarry Smith PetscReal xi[4]; 428*c6f61ee2SBarry Smith 429*c6f61ee2SBarry Smith PetscFunctionBegin; 430*c6f61ee2SBarry Smith PetscCall(PetscMalloc3(ctx->dim, &v0, ctx->dim * ctx->dim, &J, ctx->dim * ctx->dim, &invJ)); 431*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(ctx->coords, &coords)); 432*c6f61ee2SBarry Smith PetscCall(VecGetArray(v, &a)); 433*c6f61ee2SBarry Smith PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); 434*c6f61ee2SBarry Smith PetscCheck(detJ > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT, (double)detJ, c); 435*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x)); 436*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < ctx->dof; ++comp) a[p * ctx->dof + comp] = x[0 * ctx->dof + comp]; 437*c6f61ee2SBarry Smith for (PetscInt d = 0; d < ctx->dim; ++d) { 438*c6f61ee2SBarry Smith xi[d] = 0.0; 439*c6f61ee2SBarry Smith for (PetscInt f = 0; f < ctx->dim; ++f) xi[d] += invJ[d * ctx->dim + f] * 0.5 * PetscRealPart(coords[p * ctx->dim + f] - v0[f]); 440*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < ctx->dof; ++comp) a[p * ctx->dof + comp] += PetscRealPart(x[order[d] * ctx->dof + comp] - x[0 * ctx->dof + comp]) * xi[d]; 441*c6f61ee2SBarry Smith } 442*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x)); 443*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(v, &a)); 444*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(ctx->coords, &coords)); 445*c6f61ee2SBarry Smith PetscCall(PetscFree3(v0, J, invJ)); 446*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 447*c6f61ee2SBarry Smith } 448*c6f61ee2SBarry Smith 449*c6f61ee2SBarry Smith static inline PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 450*c6f61ee2SBarry Smith { 451*c6f61ee2SBarry Smith const PetscScalar *vertices = (const PetscScalar *)ctx; 452*c6f61ee2SBarry Smith const PetscScalar x0 = vertices[0]; 453*c6f61ee2SBarry Smith const PetscScalar y0 = vertices[1]; 454*c6f61ee2SBarry Smith const PetscScalar x1 = vertices[2]; 455*c6f61ee2SBarry Smith const PetscScalar y1 = vertices[3]; 456*c6f61ee2SBarry Smith const PetscScalar x2 = vertices[4]; 457*c6f61ee2SBarry Smith const PetscScalar y2 = vertices[5]; 458*c6f61ee2SBarry Smith const PetscScalar x3 = vertices[6]; 459*c6f61ee2SBarry Smith const PetscScalar y3 = vertices[7]; 460*c6f61ee2SBarry Smith const PetscScalar f_1 = x1 - x0; 461*c6f61ee2SBarry Smith const PetscScalar g_1 = y1 - y0; 462*c6f61ee2SBarry Smith const PetscScalar f_3 = x3 - x0; 463*c6f61ee2SBarry Smith const PetscScalar g_3 = y3 - y0; 464*c6f61ee2SBarry Smith const PetscScalar f_01 = x2 - x1 - x3 + x0; 465*c6f61ee2SBarry Smith const PetscScalar g_01 = y2 - y1 - y3 + y0; 466*c6f61ee2SBarry Smith const PetscScalar *ref; 467*c6f61ee2SBarry Smith PetscScalar *real; 468*c6f61ee2SBarry Smith 469*c6f61ee2SBarry Smith PetscFunctionBegin; 470*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(Xref, &ref)); 471*c6f61ee2SBarry Smith PetscCall(VecGetArray(Xreal, &real)); 472*c6f61ee2SBarry Smith { 473*c6f61ee2SBarry Smith const PetscScalar p0 = ref[0]; 474*c6f61ee2SBarry Smith const PetscScalar p1 = ref[1]; 475*c6f61ee2SBarry Smith 476*c6f61ee2SBarry Smith real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1; 477*c6f61ee2SBarry Smith real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1; 478*c6f61ee2SBarry Smith } 479*c6f61ee2SBarry Smith PetscCall(PetscLogFlops(28)); 480*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(Xref, &ref)); 481*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(Xreal, &real)); 482*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 483*c6f61ee2SBarry Smith } 484*c6f61ee2SBarry Smith 485*c6f61ee2SBarry Smith #include <petsc/private/dmimpl.h> 486*c6f61ee2SBarry Smith static inline PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 487*c6f61ee2SBarry Smith { 488*c6f61ee2SBarry Smith const PetscScalar *vertices = (const PetscScalar *)ctx; 489*c6f61ee2SBarry Smith const PetscScalar x0 = vertices[0]; 490*c6f61ee2SBarry Smith const PetscScalar y0 = vertices[1]; 491*c6f61ee2SBarry Smith const PetscScalar x1 = vertices[2]; 492*c6f61ee2SBarry Smith const PetscScalar y1 = vertices[3]; 493*c6f61ee2SBarry Smith const PetscScalar x2 = vertices[4]; 494*c6f61ee2SBarry Smith const PetscScalar y2 = vertices[5]; 495*c6f61ee2SBarry Smith const PetscScalar x3 = vertices[6]; 496*c6f61ee2SBarry Smith const PetscScalar y3 = vertices[7]; 497*c6f61ee2SBarry Smith const PetscScalar f_01 = x2 - x1 - x3 + x0; 498*c6f61ee2SBarry Smith const PetscScalar g_01 = y2 - y1 - y3 + y0; 499*c6f61ee2SBarry Smith const PetscScalar *ref; 500*c6f61ee2SBarry Smith 501*c6f61ee2SBarry Smith PetscFunctionBegin; 502*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(Xref, &ref)); 503*c6f61ee2SBarry Smith { 504*c6f61ee2SBarry Smith const PetscScalar x = ref[0]; 505*c6f61ee2SBarry Smith const PetscScalar y = ref[1]; 506*c6f61ee2SBarry Smith const PetscInt rows[2] = {0, 1}; 507*c6f61ee2SBarry Smith PetscScalar values[4]; 508*c6f61ee2SBarry Smith 509*c6f61ee2SBarry Smith values[0] = (x1 - x0 + f_01 * y) * 0.5; 510*c6f61ee2SBarry Smith values[1] = (x3 - x0 + f_01 * x) * 0.5; 511*c6f61ee2SBarry Smith values[2] = (y1 - y0 + g_01 * y) * 0.5; 512*c6f61ee2SBarry Smith values[3] = (y3 - y0 + g_01 * x) * 0.5; 513*c6f61ee2SBarry Smith PetscCall(MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES)); 514*c6f61ee2SBarry Smith } 515*c6f61ee2SBarry Smith PetscCall(PetscLogFlops(30)); 516*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(Xref, &ref)); 517*c6f61ee2SBarry Smith PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 518*c6f61ee2SBarry Smith PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 519*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 520*c6f61ee2SBarry Smith } 521*c6f61ee2SBarry Smith 522*c6f61ee2SBarry Smith static inline PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, PetscInt p, Vec xLocal, Vec v) 523*c6f61ee2SBarry Smith { 524*c6f61ee2SBarry Smith const PetscInt c = ctx->cells[p]; 525*c6f61ee2SBarry Smith PetscFE fem = NULL; 526*c6f61ee2SBarry Smith DM dmCoord; 527*c6f61ee2SBarry Smith SNES snes; 528*c6f61ee2SBarry Smith KSP ksp; 529*c6f61ee2SBarry Smith PC pc; 530*c6f61ee2SBarry Smith Vec coordsLocal, r, ref, real; 531*c6f61ee2SBarry Smith Mat J; 532*c6f61ee2SBarry Smith PetscTabulation T = NULL; 533*c6f61ee2SBarry Smith const PetscScalar *coords; 534*c6f61ee2SBarry Smith PetscScalar *a; 535*c6f61ee2SBarry Smith PetscReal xir[2] = {0., 0.}; 536*c6f61ee2SBarry Smith PetscInt Nf; 537*c6f61ee2SBarry Smith const PetscInt dof = ctx->dof; 538*c6f61ee2SBarry Smith PetscScalar *x = NULL, *vertices = NULL; 539*c6f61ee2SBarry Smith PetscScalar *xi; 540*c6f61ee2SBarry Smith PetscInt coordSize, xSize; 541*c6f61ee2SBarry Smith 542*c6f61ee2SBarry Smith PetscFunctionBegin; 543*c6f61ee2SBarry Smith PetscCall(DMGetNumFields(dm, &Nf)); 544*c6f61ee2SBarry Smith if (Nf) { 545*c6f61ee2SBarry Smith PetscObject obj; 546*c6f61ee2SBarry Smith PetscClassId id; 547*c6f61ee2SBarry Smith 548*c6f61ee2SBarry Smith PetscCall(DMGetField(dm, 0, NULL, &obj)); 549*c6f61ee2SBarry Smith PetscCall(PetscObjectGetClassId(obj, &id)); 550*c6f61ee2SBarry Smith if (id == PETSCFE_CLASSID) { 551*c6f61ee2SBarry Smith fem = (PetscFE)obj; 552*c6f61ee2SBarry Smith PetscCall(PetscFECreateTabulation(fem, 1, 1, xir, 0, &T)); 553*c6f61ee2SBarry Smith } 554*c6f61ee2SBarry Smith } 555*c6f61ee2SBarry Smith PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 556*c6f61ee2SBarry Smith PetscCall(DMGetCoordinateDM(dm, &dmCoord)); 557*c6f61ee2SBarry Smith PetscCall(SNESCreate(PETSC_COMM_SELF, &snes)); 558*c6f61ee2SBarry Smith PetscCall(SNESSetOptionsPrefix(snes, "quad_interp_")); 559*c6f61ee2SBarry Smith PetscCall(VecCreate(PETSC_COMM_SELF, &r)); 560*c6f61ee2SBarry Smith PetscCall(VecSetSizes(r, 2, 2)); 561*c6f61ee2SBarry Smith PetscCall(VecSetType(r, dm->vectype)); 562*c6f61ee2SBarry Smith PetscCall(VecDuplicate(r, &ref)); 563*c6f61ee2SBarry Smith PetscCall(VecDuplicate(r, &real)); 564*c6f61ee2SBarry Smith PetscCall(MatCreate(PETSC_COMM_SELF, &J)); 565*c6f61ee2SBarry Smith PetscCall(MatSetSizes(J, 2, 2, 2, 2)); 566*c6f61ee2SBarry Smith PetscCall(MatSetType(J, MATSEQDENSE)); 567*c6f61ee2SBarry Smith PetscCall(MatSetUp(J)); 568*c6f61ee2SBarry Smith PetscCall(SNESSetFunction(snes, r, QuadMap_Private, NULL)); 569*c6f61ee2SBarry Smith PetscCall(SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL)); 570*c6f61ee2SBarry Smith PetscCall(SNESGetKSP(snes, &ksp)); 571*c6f61ee2SBarry Smith PetscCall(KSPGetPC(ksp, &pc)); 572*c6f61ee2SBarry Smith PetscCall(PCSetType(pc, PCLU)); 573*c6f61ee2SBarry Smith PetscCall(SNESSetFromOptions(snes)); 574*c6f61ee2SBarry Smith 575*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(ctx->coords, &coords)); 576*c6f61ee2SBarry Smith PetscCall(VecGetArray(v, &a)); 577*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 578*c6f61ee2SBarry Smith PetscCheck(4 * 2 == coordSize, ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %" PetscInt_FMT " should be %d", coordSize, 4 * 2); 579*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x)); 580*c6f61ee2SBarry Smith PetscCall(SNESSetFunction(snes, NULL, NULL, vertices)); 581*c6f61ee2SBarry Smith PetscCall(SNESSetJacobian(snes, NULL, NULL, NULL, vertices)); 582*c6f61ee2SBarry Smith PetscCall(VecGetArray(real, &xi)); 583*c6f61ee2SBarry Smith xi[0] = coords[p * ctx->dim + 0]; 584*c6f61ee2SBarry Smith xi[1] = coords[p * ctx->dim + 1]; 585*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(real, &xi)); 586*c6f61ee2SBarry Smith PetscCall(SNESSolve(snes, real, ref)); 587*c6f61ee2SBarry Smith PetscCall(VecGetArray(ref, &xi)); 588*c6f61ee2SBarry Smith xir[0] = PetscRealPart(xi[0]); 589*c6f61ee2SBarry Smith xir[1] = PetscRealPart(xi[1]); 590*c6f61ee2SBarry Smith if (4 * dof == xSize) { 591*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < dof; ++comp) a[p * dof + comp] = x[0 * dof + comp] * (1 - xir[0]) * (1 - xir[1]) + x[1 * dof + comp] * xir[0] * (1 - xir[1]) + x[2 * dof + comp] * xir[0] * xir[1] + x[3 * dof + comp] * (1 - xir[0]) * xir[1]; 592*c6f61ee2SBarry Smith } else if (dof == xSize) { 593*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < dof; ++comp) a[p * dof + comp] = x[0 * dof + comp]; 594*c6f61ee2SBarry Smith } else { 595*c6f61ee2SBarry Smith PetscCheck(fem, ctx->comm, PETSC_ERR_ARG_WRONG, "Cannot have a higher order interpolant if the discretization is not PetscFE"); 596*c6f61ee2SBarry Smith xir[0] = 2.0 * xir[0] - 1.0; 597*c6f61ee2SBarry Smith xir[1] = 2.0 * xir[1] - 1.0; 598*c6f61ee2SBarry Smith PetscCall(PetscFEComputeTabulation(fem, 1, xir, 0, T)); 599*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < dof; ++comp) { 600*c6f61ee2SBarry Smith a[p * dof + comp] = 0.0; 601*c6f61ee2SBarry Smith for (PetscInt d = 0; d < xSize / dof; ++d) a[p * dof + comp] += x[d * dof + comp] * T->T[0][d * dof + comp]; 602*c6f61ee2SBarry Smith } 603*c6f61ee2SBarry Smith } 604*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(ref, &xi)); 605*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 606*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x)); 607*c6f61ee2SBarry Smith PetscCall(PetscTabulationDestroy(&T)); 608*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(v, &a)); 609*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(ctx->coords, &coords)); 610*c6f61ee2SBarry Smith 611*c6f61ee2SBarry Smith PetscCall(SNESDestroy(&snes)); 612*c6f61ee2SBarry Smith PetscCall(VecDestroy(&r)); 613*c6f61ee2SBarry Smith PetscCall(VecDestroy(&ref)); 614*c6f61ee2SBarry Smith PetscCall(VecDestroy(&real)); 615*c6f61ee2SBarry Smith PetscCall(MatDestroy(&J)); 616*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 617*c6f61ee2SBarry Smith } 618*c6f61ee2SBarry Smith 619*c6f61ee2SBarry Smith static inline PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 620*c6f61ee2SBarry Smith { 621*c6f61ee2SBarry Smith const PetscScalar *vertices = (const PetscScalar *)ctx; 622*c6f61ee2SBarry Smith const PetscScalar x0 = vertices[0]; 623*c6f61ee2SBarry Smith const PetscScalar y0 = vertices[1]; 624*c6f61ee2SBarry Smith const PetscScalar z0 = vertices[2]; 625*c6f61ee2SBarry Smith const PetscScalar x1 = vertices[9]; 626*c6f61ee2SBarry Smith const PetscScalar y1 = vertices[10]; 627*c6f61ee2SBarry Smith const PetscScalar z1 = vertices[11]; 628*c6f61ee2SBarry Smith const PetscScalar x2 = vertices[6]; 629*c6f61ee2SBarry Smith const PetscScalar y2 = vertices[7]; 630*c6f61ee2SBarry Smith const PetscScalar z2 = vertices[8]; 631*c6f61ee2SBarry Smith const PetscScalar x3 = vertices[3]; 632*c6f61ee2SBarry Smith const PetscScalar y3 = vertices[4]; 633*c6f61ee2SBarry Smith const PetscScalar z3 = vertices[5]; 634*c6f61ee2SBarry Smith const PetscScalar x4 = vertices[12]; 635*c6f61ee2SBarry Smith const PetscScalar y4 = vertices[13]; 636*c6f61ee2SBarry Smith const PetscScalar z4 = vertices[14]; 637*c6f61ee2SBarry Smith const PetscScalar x5 = vertices[15]; 638*c6f61ee2SBarry Smith const PetscScalar y5 = vertices[16]; 639*c6f61ee2SBarry Smith const PetscScalar z5 = vertices[17]; 640*c6f61ee2SBarry Smith const PetscScalar x6 = vertices[18]; 641*c6f61ee2SBarry Smith const PetscScalar y6 = vertices[19]; 642*c6f61ee2SBarry Smith const PetscScalar z6 = vertices[20]; 643*c6f61ee2SBarry Smith const PetscScalar x7 = vertices[21]; 644*c6f61ee2SBarry Smith const PetscScalar y7 = vertices[22]; 645*c6f61ee2SBarry Smith const PetscScalar z7 = vertices[23]; 646*c6f61ee2SBarry Smith const PetscScalar f_1 = x1 - x0; 647*c6f61ee2SBarry Smith const PetscScalar g_1 = y1 - y0; 648*c6f61ee2SBarry Smith const PetscScalar h_1 = z1 - z0; 649*c6f61ee2SBarry Smith const PetscScalar f_3 = x3 - x0; 650*c6f61ee2SBarry Smith const PetscScalar g_3 = y3 - y0; 651*c6f61ee2SBarry Smith const PetscScalar h_3 = z3 - z0; 652*c6f61ee2SBarry Smith const PetscScalar f_4 = x4 - x0; 653*c6f61ee2SBarry Smith const PetscScalar g_4 = y4 - y0; 654*c6f61ee2SBarry Smith const PetscScalar h_4 = z4 - z0; 655*c6f61ee2SBarry Smith const PetscScalar f_01 = x2 - x1 - x3 + x0; 656*c6f61ee2SBarry Smith const PetscScalar g_01 = y2 - y1 - y3 + y0; 657*c6f61ee2SBarry Smith const PetscScalar h_01 = z2 - z1 - z3 + z0; 658*c6f61ee2SBarry Smith const PetscScalar f_12 = x7 - x3 - x4 + x0; 659*c6f61ee2SBarry Smith const PetscScalar g_12 = y7 - y3 - y4 + y0; 660*c6f61ee2SBarry Smith const PetscScalar h_12 = z7 - z3 - z4 + z0; 661*c6f61ee2SBarry Smith const PetscScalar f_02 = x5 - x1 - x4 + x0; 662*c6f61ee2SBarry Smith const PetscScalar g_02 = y5 - y1 - y4 + y0; 663*c6f61ee2SBarry Smith const PetscScalar h_02 = z5 - z1 - z4 + z0; 664*c6f61ee2SBarry Smith const PetscScalar f_012 = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 665*c6f61ee2SBarry Smith const PetscScalar g_012 = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 666*c6f61ee2SBarry Smith const PetscScalar h_012 = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 667*c6f61ee2SBarry Smith const PetscScalar *ref; 668*c6f61ee2SBarry Smith PetscScalar *real; 669*c6f61ee2SBarry Smith 670*c6f61ee2SBarry Smith PetscFunctionBegin; 671*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(Xref, &ref)); 672*c6f61ee2SBarry Smith PetscCall(VecGetArray(Xreal, &real)); 673*c6f61ee2SBarry Smith { 674*c6f61ee2SBarry Smith const PetscScalar p0 = ref[0]; 675*c6f61ee2SBarry Smith const PetscScalar p1 = ref[1]; 676*c6f61ee2SBarry Smith const PetscScalar p2 = ref[2]; 677*c6f61ee2SBarry Smith 678*c6f61ee2SBarry Smith real[0] = x0 + f_1 * p0 + f_3 * p1 + f_4 * p2 + f_01 * p0 * p1 + f_12 * p1 * p2 + f_02 * p0 * p2 + f_012 * p0 * p1 * p2; 679*c6f61ee2SBarry Smith real[1] = y0 + g_1 * p0 + g_3 * p1 + g_4 * p2 + g_01 * p0 * p1 + g_01 * p0 * p1 + g_12 * p1 * p2 + g_02 * p0 * p2 + g_012 * p0 * p1 * p2; 680*c6f61ee2SBarry Smith real[2] = z0 + h_1 * p0 + h_3 * p1 + h_4 * p2 + h_01 * p0 * p1 + h_01 * p0 * p1 + h_12 * p1 * p2 + h_02 * p0 * p2 + h_012 * p0 * p1 * p2; 681*c6f61ee2SBarry Smith } 682*c6f61ee2SBarry Smith PetscCall(PetscLogFlops(114)); 683*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(Xref, &ref)); 684*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(Xreal, &real)); 685*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 686*c6f61ee2SBarry Smith } 687*c6f61ee2SBarry Smith 688*c6f61ee2SBarry Smith static inline PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 689*c6f61ee2SBarry Smith { 690*c6f61ee2SBarry Smith const PetscScalar *vertices = (const PetscScalar *)ctx; 691*c6f61ee2SBarry Smith const PetscScalar x0 = vertices[0]; 692*c6f61ee2SBarry Smith const PetscScalar y0 = vertices[1]; 693*c6f61ee2SBarry Smith const PetscScalar z0 = vertices[2]; 694*c6f61ee2SBarry Smith const PetscScalar x1 = vertices[9]; 695*c6f61ee2SBarry Smith const PetscScalar y1 = vertices[10]; 696*c6f61ee2SBarry Smith const PetscScalar z1 = vertices[11]; 697*c6f61ee2SBarry Smith const PetscScalar x2 = vertices[6]; 698*c6f61ee2SBarry Smith const PetscScalar y2 = vertices[7]; 699*c6f61ee2SBarry Smith const PetscScalar z2 = vertices[8]; 700*c6f61ee2SBarry Smith const PetscScalar x3 = vertices[3]; 701*c6f61ee2SBarry Smith const PetscScalar y3 = vertices[4]; 702*c6f61ee2SBarry Smith const PetscScalar z3 = vertices[5]; 703*c6f61ee2SBarry Smith const PetscScalar x4 = vertices[12]; 704*c6f61ee2SBarry Smith const PetscScalar y4 = vertices[13]; 705*c6f61ee2SBarry Smith const PetscScalar z4 = vertices[14]; 706*c6f61ee2SBarry Smith const PetscScalar x5 = vertices[15]; 707*c6f61ee2SBarry Smith const PetscScalar y5 = vertices[16]; 708*c6f61ee2SBarry Smith const PetscScalar z5 = vertices[17]; 709*c6f61ee2SBarry Smith const PetscScalar x6 = vertices[18]; 710*c6f61ee2SBarry Smith const PetscScalar y6 = vertices[19]; 711*c6f61ee2SBarry Smith const PetscScalar z6 = vertices[20]; 712*c6f61ee2SBarry Smith const PetscScalar x7 = vertices[21]; 713*c6f61ee2SBarry Smith const PetscScalar y7 = vertices[22]; 714*c6f61ee2SBarry Smith const PetscScalar z7 = vertices[23]; 715*c6f61ee2SBarry Smith const PetscScalar f_xy = x2 - x1 - x3 + x0; 716*c6f61ee2SBarry Smith const PetscScalar g_xy = y2 - y1 - y3 + y0; 717*c6f61ee2SBarry Smith const PetscScalar h_xy = z2 - z1 - z3 + z0; 718*c6f61ee2SBarry Smith const PetscScalar f_yz = x7 - x3 - x4 + x0; 719*c6f61ee2SBarry Smith const PetscScalar g_yz = y7 - y3 - y4 + y0; 720*c6f61ee2SBarry Smith const PetscScalar h_yz = z7 - z3 - z4 + z0; 721*c6f61ee2SBarry Smith const PetscScalar f_xz = x5 - x1 - x4 + x0; 722*c6f61ee2SBarry Smith const PetscScalar g_xz = y5 - y1 - y4 + y0; 723*c6f61ee2SBarry Smith const PetscScalar h_xz = z5 - z1 - z4 + z0; 724*c6f61ee2SBarry Smith const PetscScalar f_xyz = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 725*c6f61ee2SBarry Smith const PetscScalar g_xyz = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 726*c6f61ee2SBarry Smith const PetscScalar h_xyz = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 727*c6f61ee2SBarry Smith const PetscScalar *ref; 728*c6f61ee2SBarry Smith 729*c6f61ee2SBarry Smith PetscFunctionBegin; 730*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(Xref, &ref)); 731*c6f61ee2SBarry Smith { 732*c6f61ee2SBarry Smith const PetscScalar x = ref[0]; 733*c6f61ee2SBarry Smith const PetscScalar y = ref[1]; 734*c6f61ee2SBarry Smith const PetscScalar z = ref[2]; 735*c6f61ee2SBarry Smith const PetscInt rows[3] = {0, 1, 2}; 736*c6f61ee2SBarry Smith PetscScalar values[9]; 737*c6f61ee2SBarry Smith 738*c6f61ee2SBarry Smith values[0] = (x1 - x0 + f_xy * y + f_xz * z + f_xyz * y * z) / 2.0; 739*c6f61ee2SBarry Smith values[1] = (x3 - x0 + f_xy * x + f_yz * z + f_xyz * x * z) / 2.0; 740*c6f61ee2SBarry Smith values[2] = (x4 - x0 + f_yz * y + f_xz * x + f_xyz * x * y) / 2.0; 741*c6f61ee2SBarry Smith values[3] = (y1 - y0 + g_xy * y + g_xz * z + g_xyz * y * z) / 2.0; 742*c6f61ee2SBarry Smith values[4] = (y3 - y0 + g_xy * x + g_yz * z + g_xyz * x * z) / 2.0; 743*c6f61ee2SBarry Smith values[5] = (y4 - y0 + g_yz * y + g_xz * x + g_xyz * x * y) / 2.0; 744*c6f61ee2SBarry Smith values[6] = (z1 - z0 + h_xy * y + h_xz * z + h_xyz * y * z) / 2.0; 745*c6f61ee2SBarry Smith values[7] = (z3 - z0 + h_xy * x + h_yz * z + h_xyz * x * z) / 2.0; 746*c6f61ee2SBarry Smith values[8] = (z4 - z0 + h_yz * y + h_xz * x + h_xyz * x * y) / 2.0; 747*c6f61ee2SBarry Smith 748*c6f61ee2SBarry Smith PetscCall(MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES)); 749*c6f61ee2SBarry Smith } 750*c6f61ee2SBarry Smith PetscCall(PetscLogFlops(152)); 751*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(Xref, &ref)); 752*c6f61ee2SBarry Smith PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 753*c6f61ee2SBarry Smith PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 754*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 755*c6f61ee2SBarry Smith } 756*c6f61ee2SBarry Smith 757*c6f61ee2SBarry Smith static inline PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, PetscInt p, Vec xLocal, Vec v) 758*c6f61ee2SBarry Smith { 759*c6f61ee2SBarry Smith const PetscInt c = ctx->cells[p]; 760*c6f61ee2SBarry Smith DM dmCoord; 761*c6f61ee2SBarry Smith SNES snes; 762*c6f61ee2SBarry Smith KSP ksp; 763*c6f61ee2SBarry Smith PC pc; 764*c6f61ee2SBarry Smith Vec coordsLocal, r, ref, real; 765*c6f61ee2SBarry Smith Mat J; 766*c6f61ee2SBarry Smith const PetscScalar *coords; 767*c6f61ee2SBarry Smith PetscScalar *a; 768*c6f61ee2SBarry Smith PetscScalar *x = NULL, *vertices = NULL; 769*c6f61ee2SBarry Smith PetscScalar *xi; 770*c6f61ee2SBarry Smith PetscReal xir[3]; 771*c6f61ee2SBarry Smith PetscInt coordSize, xSize; 772*c6f61ee2SBarry Smith 773*c6f61ee2SBarry Smith PetscFunctionBegin; 774*c6f61ee2SBarry Smith PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 775*c6f61ee2SBarry Smith PetscCall(DMGetCoordinateDM(dm, &dmCoord)); 776*c6f61ee2SBarry Smith PetscCall(SNESCreate(PETSC_COMM_SELF, &snes)); 777*c6f61ee2SBarry Smith PetscCall(SNESSetOptionsPrefix(snes, "hex_interp_")); 778*c6f61ee2SBarry Smith PetscCall(VecCreate(PETSC_COMM_SELF, &r)); 779*c6f61ee2SBarry Smith PetscCall(VecSetSizes(r, 3, 3)); 780*c6f61ee2SBarry Smith PetscCall(VecSetType(r, dm->vectype)); 781*c6f61ee2SBarry Smith PetscCall(VecDuplicate(r, &ref)); 782*c6f61ee2SBarry Smith PetscCall(VecDuplicate(r, &real)); 783*c6f61ee2SBarry Smith PetscCall(MatCreate(PETSC_COMM_SELF, &J)); 784*c6f61ee2SBarry Smith PetscCall(MatSetSizes(J, 3, 3, 3, 3)); 785*c6f61ee2SBarry Smith PetscCall(MatSetType(J, MATSEQDENSE)); 786*c6f61ee2SBarry Smith PetscCall(MatSetUp(J)); 787*c6f61ee2SBarry Smith PetscCall(SNESSetFunction(snes, r, HexMap_Private, NULL)); 788*c6f61ee2SBarry Smith PetscCall(SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL)); 789*c6f61ee2SBarry Smith PetscCall(SNESGetKSP(snes, &ksp)); 790*c6f61ee2SBarry Smith PetscCall(KSPGetPC(ksp, &pc)); 791*c6f61ee2SBarry Smith PetscCall(PCSetType(pc, PCLU)); 792*c6f61ee2SBarry Smith PetscCall(SNESSetFromOptions(snes)); 793*c6f61ee2SBarry Smith 794*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(ctx->coords, &coords)); 795*c6f61ee2SBarry Smith PetscCall(VecGetArray(v, &a)); 796*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 797*c6f61ee2SBarry Smith PetscCheck(8 * 3 == coordSize, ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid coordinate closure size %" PetscInt_FMT " should be %d", coordSize, 8 * 3); 798*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x)); 799*c6f61ee2SBarry Smith PetscCheck((8 * ctx->dof == xSize) || (ctx->dof == xSize), ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input closure size %" PetscInt_FMT " should be %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 8 * ctx->dof, ctx->dof); 800*c6f61ee2SBarry Smith PetscCall(SNESSetFunction(snes, NULL, NULL, vertices)); 801*c6f61ee2SBarry Smith PetscCall(SNESSetJacobian(snes, NULL, NULL, NULL, vertices)); 802*c6f61ee2SBarry Smith PetscCall(VecGetArray(real, &xi)); 803*c6f61ee2SBarry Smith xi[0] = coords[p * ctx->dim + 0]; 804*c6f61ee2SBarry Smith xi[1] = coords[p * ctx->dim + 1]; 805*c6f61ee2SBarry Smith xi[2] = coords[p * ctx->dim + 2]; 806*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(real, &xi)); 807*c6f61ee2SBarry Smith PetscCall(SNESSolve(snes, real, ref)); 808*c6f61ee2SBarry Smith PetscCall(VecGetArray(ref, &xi)); 809*c6f61ee2SBarry Smith xir[0] = PetscRealPart(xi[0]); 810*c6f61ee2SBarry Smith xir[1] = PetscRealPart(xi[1]); 811*c6f61ee2SBarry Smith xir[2] = PetscRealPart(xi[2]); 812*c6f61ee2SBarry Smith if (8 * ctx->dof == xSize) { 813*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < ctx->dof; ++comp) { 814*c6f61ee2SBarry Smith a[p * ctx->dof + comp] = x[0 * ctx->dof + comp] * (1 - xir[0]) * (1 - xir[1]) * (1 - xir[2]) + x[3 * ctx->dof + comp] * xir[0] * (1 - xir[1]) * (1 - xir[2]) + x[2 * ctx->dof + comp] * xir[0] * xir[1] * (1 - xir[2]) + x[1 * ctx->dof + comp] * (1 - xir[0]) * xir[1] * (1 - xir[2]) + 815*c6f61ee2SBarry Smith x[4 * ctx->dof + comp] * (1 - xir[0]) * (1 - xir[1]) * xir[2] + x[5 * ctx->dof + comp] * xir[0] * (1 - xir[1]) * xir[2] + x[6 * ctx->dof + comp] * xir[0] * xir[1] * xir[2] + x[7 * ctx->dof + comp] * (1 - xir[0]) * xir[1] * xir[2]; 816*c6f61ee2SBarry Smith } 817*c6f61ee2SBarry Smith } else { 818*c6f61ee2SBarry Smith for (PetscInt comp = 0; comp < ctx->dof; ++comp) a[p * ctx->dof + comp] = x[0 * ctx->dof + comp]; 819*c6f61ee2SBarry Smith } 820*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(ref, &xi)); 821*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 822*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x)); 823*c6f61ee2SBarry Smith PetscCall(VecRestoreArray(v, &a)); 824*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(ctx->coords, &coords)); 825*c6f61ee2SBarry Smith 826*c6f61ee2SBarry Smith PetscCall(SNESDestroy(&snes)); 827*c6f61ee2SBarry Smith PetscCall(VecDestroy(&r)); 828*c6f61ee2SBarry Smith PetscCall(VecDestroy(&ref)); 829*c6f61ee2SBarry Smith PetscCall(VecDestroy(&real)); 830*c6f61ee2SBarry Smith PetscCall(MatDestroy(&J)); 831*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 832*c6f61ee2SBarry Smith } 833*c6f61ee2SBarry Smith 834*c6f61ee2SBarry Smith /*@C 835*c6f61ee2SBarry Smith DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points. 836*c6f61ee2SBarry Smith 837*c6f61ee2SBarry Smith Input Parameters: 838*c6f61ee2SBarry Smith + ctx - The `DMInterpolationInfo` context 839*c6f61ee2SBarry Smith . dm - The `DM` 840*c6f61ee2SBarry Smith - x - The local vector containing the field to be interpolated 841*c6f61ee2SBarry Smith 842*c6f61ee2SBarry Smith Output Parameter: 843*c6f61ee2SBarry Smith . v - The vector containing the interpolated values 844*c6f61ee2SBarry Smith 845*c6f61ee2SBarry Smith Level: beginner 846*c6f61ee2SBarry Smith 847*c6f61ee2SBarry Smith Note: 848*c6f61ee2SBarry Smith A suitable `v` can be obtained using `DMInterpolationGetVector()`. 849*c6f61ee2SBarry Smith 850*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationGetVector()`, `DMInterpolationAddPoints()`, `DMInterpolationCreate()` 851*c6f61ee2SBarry Smith @*/ 852*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v) 853*c6f61ee2SBarry Smith { 854*c6f61ee2SBarry Smith PetscDS ds; 855*c6f61ee2SBarry Smith PetscInt n, p, Nf, field; 856*c6f61ee2SBarry Smith PetscBool useDS = PETSC_FALSE; 857*c6f61ee2SBarry Smith 858*c6f61ee2SBarry Smith PetscFunctionBegin; 859*c6f61ee2SBarry Smith PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 860*c6f61ee2SBarry Smith PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 861*c6f61ee2SBarry Smith PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 862*c6f61ee2SBarry Smith PetscCall(VecGetLocalSize(v, &n)); 863*c6f61ee2SBarry Smith PetscCheck(n == ctx->n * ctx->dof, ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %" PetscInt_FMT " should be %" PetscInt_FMT, n, ctx->n * ctx->dof); 864*c6f61ee2SBarry Smith if (!n) PetscFunctionReturn(PETSC_SUCCESS); 865*c6f61ee2SBarry Smith PetscCall(DMGetDS(dm, &ds)); 866*c6f61ee2SBarry Smith if (ds) { 867*c6f61ee2SBarry Smith useDS = PETSC_TRUE; 868*c6f61ee2SBarry Smith PetscCall(PetscDSGetNumFields(ds, &Nf)); 869*c6f61ee2SBarry Smith for (field = 0; field < Nf; ++field) { 870*c6f61ee2SBarry Smith PetscObject obj; 871*c6f61ee2SBarry Smith PetscClassId id; 872*c6f61ee2SBarry Smith 873*c6f61ee2SBarry Smith PetscCall(PetscDSGetDiscretization(ds, field, &obj)); 874*c6f61ee2SBarry Smith PetscCall(PetscObjectGetClassId(obj, &id)); 875*c6f61ee2SBarry Smith if (id != PETSCFE_CLASSID && id != PETSCFV_CLASSID) { 876*c6f61ee2SBarry Smith useDS = PETSC_FALSE; 877*c6f61ee2SBarry Smith break; 878*c6f61ee2SBarry Smith } 879*c6f61ee2SBarry Smith } 880*c6f61ee2SBarry Smith } 881*c6f61ee2SBarry Smith if (useDS) { 882*c6f61ee2SBarry Smith const PetscScalar *coords; 883*c6f61ee2SBarry Smith PetscScalar *interpolant; 884*c6f61ee2SBarry Smith PetscInt cdim, d; 885*c6f61ee2SBarry Smith 886*c6f61ee2SBarry Smith PetscCall(DMGetCoordinateDim(dm, &cdim)); 887*c6f61ee2SBarry Smith PetscCall(VecGetArrayRead(ctx->coords, &coords)); 888*c6f61ee2SBarry Smith PetscCall(VecGetArrayWrite(v, &interpolant)); 889*c6f61ee2SBarry Smith for (p = 0; p < ctx->n; ++p) { 890*c6f61ee2SBarry Smith PetscReal pcoords[3], xi[3]; 891*c6f61ee2SBarry Smith PetscScalar *xa = NULL; 892*c6f61ee2SBarry Smith PetscInt coff = 0, foff = 0, clSize; 893*c6f61ee2SBarry Smith 894*c6f61ee2SBarry Smith if (ctx->cells[p] < 0) continue; 895*c6f61ee2SBarry Smith for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p * cdim + d]); 896*c6f61ee2SBarry Smith PetscCall(DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi)); 897*c6f61ee2SBarry Smith PetscCall(DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa)); 898*c6f61ee2SBarry Smith for (field = 0; field < Nf; ++field) { 899*c6f61ee2SBarry Smith PetscTabulation T; 900*c6f61ee2SBarry Smith PetscObject obj; 901*c6f61ee2SBarry Smith PetscClassId id; 902*c6f61ee2SBarry Smith 903*c6f61ee2SBarry Smith PetscCall(PetscDSGetDiscretization(ds, field, &obj)); 904*c6f61ee2SBarry Smith PetscCall(PetscObjectGetClassId(obj, &id)); 905*c6f61ee2SBarry Smith if (id == PETSCFE_CLASSID) { 906*c6f61ee2SBarry Smith PetscFE fe = (PetscFE)obj; 907*c6f61ee2SBarry Smith 908*c6f61ee2SBarry Smith PetscCall(PetscFECreateTabulation(fe, 1, 1, xi, 0, &T)); 909*c6f61ee2SBarry Smith { 910*c6f61ee2SBarry Smith const PetscReal *basis = T->T[0]; 911*c6f61ee2SBarry Smith const PetscInt Nb = T->Nb; 912*c6f61ee2SBarry Smith const PetscInt Nc = T->Nc; 913*c6f61ee2SBarry Smith 914*c6f61ee2SBarry Smith for (PetscInt fc = 0; fc < Nc; ++fc) { 915*c6f61ee2SBarry Smith interpolant[p * ctx->dof + coff + fc] = 0.0; 916*c6f61ee2SBarry Smith for (PetscInt f = 0; f < Nb; ++f) interpolant[p * ctx->dof + coff + fc] += xa[foff + f] * basis[(0 * Nb + f) * Nc + fc]; 917*c6f61ee2SBarry Smith } 918*c6f61ee2SBarry Smith coff += Nc; 919*c6f61ee2SBarry Smith foff += Nb; 920*c6f61ee2SBarry Smith } 921*c6f61ee2SBarry Smith PetscCall(PetscTabulationDestroy(&T)); 922*c6f61ee2SBarry Smith } else if (id == PETSCFV_CLASSID) { 923*c6f61ee2SBarry Smith PetscFV fv = (PetscFV)obj; 924*c6f61ee2SBarry Smith PetscInt Nc; 925*c6f61ee2SBarry Smith 926*c6f61ee2SBarry Smith // TODO Could use reconstruction if available 927*c6f61ee2SBarry Smith PetscCall(PetscFVGetNumComponents(fv, &Nc)); 928*c6f61ee2SBarry Smith for (PetscInt fc = 0; fc < Nc; ++fc) interpolant[p * ctx->dof + coff + fc] = xa[foff + fc]; 929*c6f61ee2SBarry Smith coff += Nc; 930*c6f61ee2SBarry Smith foff += Nc; 931*c6f61ee2SBarry Smith } 932*c6f61ee2SBarry Smith } 933*c6f61ee2SBarry Smith PetscCall(DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa)); 934*c6f61ee2SBarry Smith PetscCheck(coff == ctx->dof, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %" PetscInt_FMT " != %" PetscInt_FMT " dof specified for interpolation", coff, ctx->dof); 935*c6f61ee2SBarry Smith PetscCheck(foff == clSize, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total FE/FV space size %" PetscInt_FMT " != %" PetscInt_FMT " closure size", foff, clSize); 936*c6f61ee2SBarry Smith } 937*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayRead(ctx->coords, &coords)); 938*c6f61ee2SBarry Smith PetscCall(VecRestoreArrayWrite(v, &interpolant)); 939*c6f61ee2SBarry Smith } else { 940*c6f61ee2SBarry Smith for (PetscInt p = 0; p < ctx->n; ++p) { 941*c6f61ee2SBarry Smith const PetscInt cell = ctx->cells[p]; 942*c6f61ee2SBarry Smith DMPolytopeType ct; 943*c6f61ee2SBarry Smith 944*c6f61ee2SBarry Smith PetscCall(DMPlexGetCellType(dm, cell, &ct)); 945*c6f61ee2SBarry Smith switch (ct) { 946*c6f61ee2SBarry Smith case DM_POLYTOPE_SEGMENT: 947*c6f61ee2SBarry Smith PetscCall(DMInterpolate_Segment_Private(ctx, dm, p, x, v)); 948*c6f61ee2SBarry Smith break; 949*c6f61ee2SBarry Smith case DM_POLYTOPE_TRIANGLE: 950*c6f61ee2SBarry Smith PetscCall(DMInterpolate_Triangle_Private(ctx, dm, p, x, v)); 951*c6f61ee2SBarry Smith break; 952*c6f61ee2SBarry Smith case DM_POLYTOPE_QUADRILATERAL: 953*c6f61ee2SBarry Smith PetscCall(DMInterpolate_Quad_Private(ctx, dm, p, x, v)); 954*c6f61ee2SBarry Smith break; 955*c6f61ee2SBarry Smith case DM_POLYTOPE_TETRAHEDRON: 956*c6f61ee2SBarry Smith PetscCall(DMInterpolate_Tetrahedron_Private(ctx, dm, p, x, v)); 957*c6f61ee2SBarry Smith break; 958*c6f61ee2SBarry Smith case DM_POLYTOPE_HEXAHEDRON: 959*c6f61ee2SBarry Smith PetscCall(DMInterpolate_Hex_Private(ctx, dm, cell, x, v)); 960*c6f61ee2SBarry Smith break; 961*c6f61ee2SBarry Smith default: 962*c6f61ee2SBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for cell type %s", DMPolytopeTypes[PetscMax(0, PetscMin(ct, DM_NUM_POLYTOPES))]); 963*c6f61ee2SBarry Smith } 964*c6f61ee2SBarry Smith } 965*c6f61ee2SBarry Smith } 966*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 967*c6f61ee2SBarry Smith } 968*c6f61ee2SBarry Smith 969*c6f61ee2SBarry Smith /*@C 970*c6f61ee2SBarry Smith DMInterpolationDestroy - Destroys a `DMInterpolationInfo` context 971*c6f61ee2SBarry Smith 972*c6f61ee2SBarry Smith Collective 973*c6f61ee2SBarry Smith 974*c6f61ee2SBarry Smith Input Parameter: 975*c6f61ee2SBarry Smith . ctx - the context 976*c6f61ee2SBarry Smith 977*c6f61ee2SBarry Smith Level: beginner 978*c6f61ee2SBarry Smith 979*c6f61ee2SBarry Smith .seealso: [](ch_snes), `DM`, `DMInterpolationInfo`, `DMInterpolationEvaluate()`, `DMInterpolationAddPoints()`, `DMInterpolationCreate()` 980*c6f61ee2SBarry Smith @*/ 981*c6f61ee2SBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx) 982*c6f61ee2SBarry Smith { 983*c6f61ee2SBarry Smith PetscFunctionBegin; 984*c6f61ee2SBarry Smith PetscAssertPointer(ctx, 1); 985*c6f61ee2SBarry Smith PetscCall(VecDestroy(&(*ctx)->coords)); 986*c6f61ee2SBarry Smith PetscCall(PetscFree((*ctx)->points)); 987*c6f61ee2SBarry Smith PetscCall(PetscFree((*ctx)->cells)); 988*c6f61ee2SBarry Smith PetscCall(PetscFree(*ctx)); 989*c6f61ee2SBarry Smith *ctx = NULL; 990*c6f61ee2SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 991*c6f61ee2SBarry Smith } 992