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