1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 324cdb843SMatthew G. Knepley #include <petscds.h> 4a925c78cSMatthew G. Knepley #include <petscblaslapack.h> 5af0996ceSBarry Smith #include <petsc/private/petscimpl.h> 6af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 7552f7358SJed Brown 89044fa66SMatthew G. Knepley static PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points) 99044fa66SMatthew G. Knepley { 109044fa66SMatthew G. Knepley PetscInt numCells, step = 1; 119044fa66SMatthew G. Knepley PetscBool isStride; 129044fa66SMatthew G. Knepley PetscErrorCode ierr; 139044fa66SMatthew G. Knepley 149044fa66SMatthew G. Knepley PetscFunctionBeginHot; 159044fa66SMatthew G. Knepley *pStart = 0; 169044fa66SMatthew G. Knepley *points = NULL; 179044fa66SMatthew G. Knepley ierr = ISGetLocalSize(pointIS, &numCells);CHKERRQ(ierr); 189044fa66SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr); 199044fa66SMatthew G. Knepley if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);} 209044fa66SMatthew G. Knepley *pEnd = *pStart + numCells; 219044fa66SMatthew G. Knepley if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);} 229044fa66SMatthew G. Knepley PetscFunctionReturn(0); 239044fa66SMatthew G. Knepley } 249044fa66SMatthew G. Knepley 259044fa66SMatthew G. Knepley static PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points) 269044fa66SMatthew G. Knepley { 279044fa66SMatthew G. Knepley PetscInt step = 1; 289044fa66SMatthew G. Knepley PetscBool isStride; 299044fa66SMatthew G. Knepley PetscErrorCode ierr; 309044fa66SMatthew G. Knepley 319044fa66SMatthew G. Knepley PetscFunctionBeginHot; 329044fa66SMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) pointIS, ISSTRIDE, &isStride);CHKERRQ(ierr); 339044fa66SMatthew G. Knepley if (isStride) {ierr = ISStrideGetInfo(pointIS, pStart, &step);CHKERRQ(ierr);} 349044fa66SMatthew G. Knepley if (!isStride || step != 1) {ierr = ISGetIndices(pointIS, points);CHKERRQ(ierr);} 359044fa66SMatthew G. Knepley PetscFunctionReturn(0); 369044fa66SMatthew G. Knepley } 379044fa66SMatthew G. Knepley 389044fa66SMatthew G. Knepley static PetscErrorCode ISGetPointSubrange(IS subpointIS, PetscInt pStart, PetscInt pEnd, const PetscInt *points) 399044fa66SMatthew G. Knepley { 409044fa66SMatthew G. Knepley PetscErrorCode ierr; 419044fa66SMatthew G. Knepley 429044fa66SMatthew G. Knepley PetscFunctionBeginHot; 439044fa66SMatthew G. Knepley if (points) { 449044fa66SMatthew G. Knepley ierr = ISSetType(subpointIS, ISGENERAL);CHKERRQ(ierr); 459044fa66SMatthew G. Knepley ierr = ISGeneralSetIndices(subpointIS, pEnd-pStart, &points[pStart], PETSC_USE_POINTER);CHKERRQ(ierr); 469044fa66SMatthew G. Knepley } else { 479044fa66SMatthew G. Knepley ierr = ISSetType(subpointIS, ISSTRIDE);CHKERRQ(ierr); 489044fa66SMatthew G. Knepley ierr = ISStrideSetStride(subpointIS, pEnd-pStart, pStart, 1);CHKERRQ(ierr); 499044fa66SMatthew G. Knepley } 509044fa66SMatthew G. Knepley PetscFunctionReturn(0); 519044fa66SMatthew G. Knepley } 529044fa66SMatthew G. Knepley 5324cdb843SMatthew G. Knepley /************************** Interpolation *******************************/ 5424cdb843SMatthew G. Knepley 556da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy) 566da023fcSToby Isaac { 576da023fcSToby Isaac PetscBool isPlex; 586da023fcSToby Isaac PetscErrorCode ierr; 596da023fcSToby Isaac 606da023fcSToby Isaac PetscFunctionBegin; 616da023fcSToby Isaac ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr); 626da023fcSToby Isaac if (isPlex) { 636da023fcSToby Isaac *plex = dm; 646da023fcSToby Isaac ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 65f7148743SMatthew G. Knepley } else { 66f7148743SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex);CHKERRQ(ierr); 67f7148743SMatthew G. Knepley if (!*plex) { 686da023fcSToby Isaac ierr = DMConvert(dm,DMPLEX,plex);CHKERRQ(ierr); 69f7148743SMatthew G. Knepley ierr = PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex);CHKERRQ(ierr); 706da023fcSToby Isaac if (copy) { 716da023fcSToby Isaac PetscInt i; 726da023fcSToby Isaac PetscObject obj; 736da023fcSToby Isaac const char *comps[3] = {"A","dmAux","dmCh"}; 746da023fcSToby Isaac 756da023fcSToby Isaac ierr = DMCopyDMSNES(dm, *plex);CHKERRQ(ierr); 766da023fcSToby Isaac for (i = 0; i < 3; i++) { 776da023fcSToby Isaac ierr = PetscObjectQuery((PetscObject) dm, comps[i], &obj);CHKERRQ(ierr); 786da023fcSToby Isaac ierr = PetscObjectCompose((PetscObject) *plex, comps[i], obj);CHKERRQ(ierr); 796da023fcSToby Isaac } 806da023fcSToby Isaac } 81f7148743SMatthew G. Knepley } else { 82f7148743SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) *plex);CHKERRQ(ierr); 83f7148743SMatthew G. Knepley } 846da023fcSToby Isaac } 856da023fcSToby Isaac PetscFunctionReturn(0); 866da023fcSToby Isaac } 876da023fcSToby Isaac 880adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx) 890adebc6cSBarry Smith { 90552f7358SJed Brown PetscErrorCode ierr; 91552f7358SJed Brown 92552f7358SJed Brown PetscFunctionBegin; 93552f7358SJed Brown PetscValidPointer(ctx, 2); 9495dccacaSBarry Smith ierr = PetscNew(ctx);CHKERRQ(ierr); 951aa26658SKarl Rupp 96552f7358SJed Brown (*ctx)->comm = comm; 97552f7358SJed Brown (*ctx)->dim = -1; 98552f7358SJed Brown (*ctx)->nInput = 0; 990298fd71SBarry Smith (*ctx)->points = NULL; 1000298fd71SBarry Smith (*ctx)->cells = NULL; 101552f7358SJed Brown (*ctx)->n = -1; 1020298fd71SBarry Smith (*ctx)->coords = NULL; 103552f7358SJed Brown PetscFunctionReturn(0); 104552f7358SJed Brown } 105552f7358SJed Brown 1060adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim) 1070adebc6cSBarry Smith { 108552f7358SJed Brown PetscFunctionBegin; 1090adebc6cSBarry Smith if ((dim < 1) || (dim > 3)) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %d", dim); 110552f7358SJed Brown ctx->dim = dim; 111552f7358SJed Brown PetscFunctionReturn(0); 112552f7358SJed Brown } 113552f7358SJed Brown 1140adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim) 1150adebc6cSBarry Smith { 116552f7358SJed Brown PetscFunctionBegin; 117552f7358SJed Brown PetscValidIntPointer(dim, 2); 118552f7358SJed Brown *dim = ctx->dim; 119552f7358SJed Brown PetscFunctionReturn(0); 120552f7358SJed Brown } 121552f7358SJed Brown 1220adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof) 1230adebc6cSBarry Smith { 124552f7358SJed Brown PetscFunctionBegin; 1250adebc6cSBarry Smith if (dof < 1) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %d", dof); 126552f7358SJed Brown ctx->dof = dof; 127552f7358SJed Brown PetscFunctionReturn(0); 128552f7358SJed Brown } 129552f7358SJed Brown 1300adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof) 1310adebc6cSBarry Smith { 132552f7358SJed Brown PetscFunctionBegin; 133552f7358SJed Brown PetscValidIntPointer(dof, 2); 134552f7358SJed Brown *dof = ctx->dof; 135552f7358SJed Brown PetscFunctionReturn(0); 136552f7358SJed Brown } 137552f7358SJed Brown 1380adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[]) 1390adebc6cSBarry Smith { 140552f7358SJed Brown PetscErrorCode ierr; 141552f7358SJed Brown 142552f7358SJed Brown PetscFunctionBegin; 1430adebc6cSBarry Smith if (ctx->dim < 0) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 1440adebc6cSBarry Smith if (ctx->points) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet"); 145552f7358SJed Brown ctx->nInput = n; 1461aa26658SKarl Rupp 147785e854fSJed Brown ierr = PetscMalloc1(n*ctx->dim, &ctx->points);CHKERRQ(ierr); 148552f7358SJed Brown ierr = PetscMemcpy(ctx->points, points, n*ctx->dim * sizeof(PetscReal));CHKERRQ(ierr); 149552f7358SJed Brown PetscFunctionReturn(0); 150552f7358SJed Brown } 151552f7358SJed Brown 1520adebc6cSBarry Smith PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints) 1530adebc6cSBarry Smith { 154552f7358SJed Brown MPI_Comm comm = ctx->comm; 155552f7358SJed Brown PetscScalar *a; 156552f7358SJed Brown PetscInt p, q, i; 157552f7358SJed Brown PetscMPIInt rank, size; 158552f7358SJed Brown PetscErrorCode ierr; 159552f7358SJed Brown Vec pointVec; 1603a93e3b7SToby Isaac PetscSF cellSF; 161552f7358SJed Brown PetscLayout layout; 162552f7358SJed Brown PetscReal *globalPoints; 163cb313848SJed Brown PetscScalar *globalPointsScalar; 164552f7358SJed Brown const PetscInt *ranges; 165552f7358SJed Brown PetscMPIInt *counts, *displs; 1663a93e3b7SToby Isaac const PetscSFNode *foundCells; 1673a93e3b7SToby Isaac const PetscInt *foundPoints; 168552f7358SJed Brown PetscMPIInt *foundProcs, *globalProcs; 1693a93e3b7SToby Isaac PetscInt n, N, numFound; 170552f7358SJed Brown 17119436ca2SJed Brown PetscFunctionBegin; 17219436ca2SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 17319436ca2SJed Brown ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 17419436ca2SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1750adebc6cSBarry Smith if (ctx->dim < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 17619436ca2SJed Brown /* Locate points */ 17719436ca2SJed Brown n = ctx->nInput; 178552f7358SJed Brown if (!redundantPoints) { 179552f7358SJed Brown ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 180552f7358SJed Brown ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 181552f7358SJed Brown ierr = PetscLayoutSetLocalSize(layout, n);CHKERRQ(ierr); 182552f7358SJed Brown ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 183552f7358SJed Brown ierr = PetscLayoutGetSize(layout, &N);CHKERRQ(ierr); 184552f7358SJed Brown /* Communicate all points to all processes */ 185dcca6d9dSJed Brown ierr = PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs);CHKERRQ(ierr); 186552f7358SJed Brown ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 187552f7358SJed Brown for (p = 0; p < size; ++p) { 188552f7358SJed Brown counts[p] = (ranges[p+1] - ranges[p])*ctx->dim; 189552f7358SJed Brown displs[p] = ranges[p]*ctx->dim; 190552f7358SJed Brown } 191552f7358SJed Brown ierr = MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm);CHKERRQ(ierr); 192552f7358SJed Brown } else { 193552f7358SJed Brown N = n; 194552f7358SJed Brown globalPoints = ctx->points; 19538ea73c8SJed Brown counts = displs = NULL; 19638ea73c8SJed Brown layout = NULL; 197552f7358SJed Brown } 198552f7358SJed Brown #if 0 199dcca6d9dSJed Brown ierr = PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs);CHKERRQ(ierr); 20019436ca2SJed Brown /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */ 201552f7358SJed Brown #else 202cb313848SJed Brown #if defined(PETSC_USE_COMPLEX) 20346b3086cSToby Isaac ierr = PetscMalloc1(N*ctx->dim,&globalPointsScalar);CHKERRQ(ierr); 20446b3086cSToby Isaac for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i]; 205cb313848SJed Brown #else 206cb313848SJed Brown globalPointsScalar = globalPoints; 207cb313848SJed Brown #endif 20804706141SMatthew G Knepley ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec);CHKERRQ(ierr); 209dcca6d9dSJed Brown ierr = PetscMalloc2(N,&foundProcs,N,&globalProcs);CHKERRQ(ierr); 2107b5f2079SMatthew G. Knepley for (p = 0; p < N; ++p) {foundProcs[p] = size;} 2113a93e3b7SToby Isaac cellSF = NULL; 2122d1fa6caSMatthew G. Knepley ierr = DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF);CHKERRQ(ierr); 2133a93e3b7SToby Isaac ierr = PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells);CHKERRQ(ierr); 214552f7358SJed Brown #endif 2153a93e3b7SToby Isaac for (p = 0; p < numFound; ++p) { 2163a93e3b7SToby Isaac if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank; 217552f7358SJed Brown } 218552f7358SJed Brown /* Let the lowest rank process own each point */ 219b2566f29SBarry Smith ierr = MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm);CHKERRQ(ierr); 220552f7358SJed Brown ctx->n = 0; 221552f7358SJed Brown for (p = 0; p < N; ++p) { 222e5b268a4SToby Isaac if (globalProcs[p] == size) SETERRQ4(comm, PETSC_ERR_PLIB, "Point %d: %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), (double)(ctx->dim > 2 ? globalPoints[p*ctx->dim+2] : 0.0)); 2231aa26658SKarl Rupp else if (globalProcs[p] == rank) ctx->n++; 224552f7358SJed Brown } 225552f7358SJed Brown /* Create coordinates vector and array of owned cells */ 226785e854fSJed Brown ierr = PetscMalloc1(ctx->n, &ctx->cells);CHKERRQ(ierr); 227552f7358SJed Brown ierr = VecCreate(comm, &ctx->coords);CHKERRQ(ierr); 228552f7358SJed Brown ierr = VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE);CHKERRQ(ierr); 229552f7358SJed Brown ierr = VecSetBlockSize(ctx->coords, ctx->dim);CHKERRQ(ierr); 230c0dedaeaSBarry Smith ierr = VecSetType(ctx->coords,VECSTANDARD);CHKERRQ(ierr); 231552f7358SJed Brown ierr = VecGetArray(ctx->coords, &a);CHKERRQ(ierr); 232552f7358SJed Brown for (p = 0, q = 0, i = 0; p < N; ++p) { 233552f7358SJed Brown if (globalProcs[p] == rank) { 234552f7358SJed Brown PetscInt d; 235552f7358SJed Brown 2361aa26658SKarl Rupp for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d]; 237f317b747SMatthew G. Knepley ctx->cells[q] = foundCells[q].index; 238f317b747SMatthew G. Knepley ++q; 239552f7358SJed Brown } 240552f7358SJed Brown } 241552f7358SJed Brown ierr = VecRestoreArray(ctx->coords, &a);CHKERRQ(ierr); 242552f7358SJed Brown #if 0 243552f7358SJed Brown ierr = PetscFree3(foundCells,foundProcs,globalProcs);CHKERRQ(ierr); 244552f7358SJed Brown #else 245552f7358SJed Brown ierr = PetscFree2(foundProcs,globalProcs);CHKERRQ(ierr); 2463a93e3b7SToby Isaac ierr = PetscSFDestroy(&cellSF);CHKERRQ(ierr); 247552f7358SJed Brown ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 248552f7358SJed Brown #endif 249cb313848SJed Brown if ((void*)globalPointsScalar != (void*)globalPoints) {ierr = PetscFree(globalPointsScalar);CHKERRQ(ierr);} 250d343d804SMatthew G. Knepley if (!redundantPoints) {ierr = PetscFree3(globalPoints,counts,displs);CHKERRQ(ierr);} 251552f7358SJed Brown ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 252552f7358SJed Brown PetscFunctionReturn(0); 253552f7358SJed Brown } 254552f7358SJed Brown 2550adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates) 2560adebc6cSBarry Smith { 257552f7358SJed Brown PetscFunctionBegin; 258552f7358SJed Brown PetscValidPointer(coordinates, 2); 2590adebc6cSBarry Smith if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 260552f7358SJed Brown *coordinates = ctx->coords; 261552f7358SJed Brown PetscFunctionReturn(0); 262552f7358SJed Brown } 263552f7358SJed Brown 2640adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v) 2650adebc6cSBarry Smith { 266552f7358SJed Brown PetscErrorCode ierr; 267552f7358SJed Brown 268552f7358SJed Brown PetscFunctionBegin; 269552f7358SJed Brown PetscValidPointer(v, 2); 2700adebc6cSBarry Smith if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 271552f7358SJed Brown ierr = VecCreate(ctx->comm, v);CHKERRQ(ierr); 272552f7358SJed Brown ierr = VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE);CHKERRQ(ierr); 273552f7358SJed Brown ierr = VecSetBlockSize(*v, ctx->dof);CHKERRQ(ierr); 274c0dedaeaSBarry Smith ierr = VecSetType(*v,VECSTANDARD);CHKERRQ(ierr); 275552f7358SJed Brown PetscFunctionReturn(0); 276552f7358SJed Brown } 277552f7358SJed Brown 2780adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v) 2790adebc6cSBarry Smith { 280552f7358SJed Brown PetscErrorCode ierr; 281552f7358SJed Brown 282552f7358SJed Brown PetscFunctionBegin; 283552f7358SJed Brown PetscValidPointer(v, 2); 2840adebc6cSBarry Smith if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 285552f7358SJed Brown ierr = VecDestroy(v);CHKERRQ(ierr); 286552f7358SJed Brown PetscFunctionReturn(0); 287552f7358SJed Brown } 288552f7358SJed Brown 2897a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 290a6dfd86eSKarl Rupp { 291552f7358SJed Brown PetscReal *v0, *J, *invJ, detJ; 29256044e6dSMatthew G. Knepley const PetscScalar *coords; 29356044e6dSMatthew G. Knepley PetscScalar *a; 294552f7358SJed Brown PetscInt p; 295552f7358SJed Brown PetscErrorCode ierr; 296552f7358SJed Brown 297552f7358SJed Brown PetscFunctionBegin; 298dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 29956044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 300552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 301552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 302552f7358SJed Brown PetscInt c = ctx->cells[p]; 303a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 304552f7358SJed Brown PetscReal xi[4]; 305552f7358SJed Brown PetscInt d, f, comp; 306552f7358SJed Brown 3078e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 308e5b268a4SToby Isaac if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", (double)detJ, c); 3090298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 3101aa26658SKarl Rupp for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 3111aa26658SKarl Rupp 312552f7358SJed Brown for (d = 0; d < ctx->dim; ++d) { 313552f7358SJed Brown xi[d] = 0.0; 3141aa26658SKarl Rupp for (f = 0; f < ctx->dim; ++f) xi[d] += invJ[d*ctx->dim+f]*0.5*PetscRealPart(coords[p*ctx->dim+f] - v0[f]); 3151aa26658SKarl Rupp for (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]; 316552f7358SJed Brown } 3170298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 318552f7358SJed Brown } 319552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 32056044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 321552f7358SJed Brown ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 322552f7358SJed Brown PetscFunctionReturn(0); 323552f7358SJed Brown } 324552f7358SJed Brown 3257a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 3267a1931ceSMatthew G. Knepley { 3277a1931ceSMatthew G. Knepley PetscReal *v0, *J, *invJ, detJ; 32856044e6dSMatthew G. Knepley const PetscScalar *coords; 32956044e6dSMatthew G. Knepley PetscScalar *a; 3307a1931ceSMatthew G. Knepley PetscInt p; 3317a1931ceSMatthew G. Knepley PetscErrorCode ierr; 3327a1931ceSMatthew G. Knepley 3337a1931ceSMatthew G. Knepley PetscFunctionBegin; 334dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 33556044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 3367a1931ceSMatthew G. Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 3377a1931ceSMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 3387a1931ceSMatthew G. Knepley PetscInt c = ctx->cells[p]; 3397a1931ceSMatthew G. Knepley const PetscInt order[3] = {2, 1, 3}; 3402584bbe8SMatthew G. Knepley PetscScalar *x = NULL; 3417a1931ceSMatthew G. Knepley PetscReal xi[4]; 3427a1931ceSMatthew G. Knepley PetscInt d, f, comp; 3437a1931ceSMatthew G. Knepley 3448e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 345e5b268a4SToby Isaac if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", (double)detJ, c); 3467a1931ceSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 3477a1931ceSMatthew G. Knepley for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 3487a1931ceSMatthew G. Knepley 3497a1931ceSMatthew G. Knepley for (d = 0; d < ctx->dim; ++d) { 3507a1931ceSMatthew G. Knepley xi[d] = 0.0; 3517a1931ceSMatthew G. Knepley for (f = 0; f < ctx->dim; ++f) xi[d] += invJ[d*ctx->dim+f]*0.5*PetscRealPart(coords[p*ctx->dim+f] - v0[f]); 3527a1931ceSMatthew G. Knepley for (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]; 3537a1931ceSMatthew G. Knepley } 3547a1931ceSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 3557a1931ceSMatthew G. Knepley } 3567a1931ceSMatthew G. Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 35756044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 3587a1931ceSMatthew G. Knepley ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 3597a1931ceSMatthew G. Knepley PetscFunctionReturn(0); 3607a1931ceSMatthew G. Knepley } 3617a1931ceSMatthew G. Knepley 3625820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 363552f7358SJed Brown { 364552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 365552f7358SJed Brown const PetscScalar x0 = vertices[0]; 366552f7358SJed Brown const PetscScalar y0 = vertices[1]; 367552f7358SJed Brown const PetscScalar x1 = vertices[2]; 368552f7358SJed Brown const PetscScalar y1 = vertices[3]; 369552f7358SJed Brown const PetscScalar x2 = vertices[4]; 370552f7358SJed Brown const PetscScalar y2 = vertices[5]; 371552f7358SJed Brown const PetscScalar x3 = vertices[6]; 372552f7358SJed Brown const PetscScalar y3 = vertices[7]; 373552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 374552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 375552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 376552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 377552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 378552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 37956044e6dSMatthew G. Knepley const PetscScalar *ref; 38056044e6dSMatthew G. Knepley PetscScalar *real; 381552f7358SJed Brown PetscErrorCode ierr; 382552f7358SJed Brown 383552f7358SJed Brown PetscFunctionBegin; 38456044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 385552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 386552f7358SJed Brown { 387552f7358SJed Brown const PetscScalar p0 = ref[0]; 388552f7358SJed Brown const PetscScalar p1 = ref[1]; 389552f7358SJed Brown 390552f7358SJed Brown real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1; 391552f7358SJed Brown real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1; 392552f7358SJed Brown } 393552f7358SJed Brown ierr = PetscLogFlops(28);CHKERRQ(ierr); 39456044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 395552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 396552f7358SJed Brown PetscFunctionReturn(0); 397552f7358SJed Brown } 398552f7358SJed Brown 399af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 400d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 401552f7358SJed Brown { 402552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 403552f7358SJed Brown const PetscScalar x0 = vertices[0]; 404552f7358SJed Brown const PetscScalar y0 = vertices[1]; 405552f7358SJed Brown const PetscScalar x1 = vertices[2]; 406552f7358SJed Brown const PetscScalar y1 = vertices[3]; 407552f7358SJed Brown const PetscScalar x2 = vertices[4]; 408552f7358SJed Brown const PetscScalar y2 = vertices[5]; 409552f7358SJed Brown const PetscScalar x3 = vertices[6]; 410552f7358SJed Brown const PetscScalar y3 = vertices[7]; 411552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 412552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 41356044e6dSMatthew G. Knepley const PetscScalar *ref; 414552f7358SJed Brown PetscErrorCode ierr; 415552f7358SJed Brown 416552f7358SJed Brown PetscFunctionBegin; 41756044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 418552f7358SJed Brown { 419552f7358SJed Brown const PetscScalar x = ref[0]; 420552f7358SJed Brown const PetscScalar y = ref[1]; 421552f7358SJed Brown const PetscInt rows[2] = {0, 1}; 422da80777bSKarl Rupp PetscScalar values[4]; 423da80777bSKarl Rupp 424da80777bSKarl Rupp values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5; 425da80777bSKarl Rupp values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5; 42694ab13aaSBarry Smith ierr = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr); 427552f7358SJed Brown } 428552f7358SJed Brown ierr = PetscLogFlops(30);CHKERRQ(ierr); 42956044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 43094ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 43194ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 432552f7358SJed Brown PetscFunctionReturn(0); 433552f7358SJed Brown } 434552f7358SJed Brown 435a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 436a6dfd86eSKarl Rupp { 437fafc0619SMatthew G Knepley DM dmCoord; 438de73a395SMatthew G. Knepley PetscFE fem = NULL; 439552f7358SJed Brown SNES snes; 440552f7358SJed Brown KSP ksp; 441552f7358SJed Brown PC pc; 442552f7358SJed Brown Vec coordsLocal, r, ref, real; 443552f7358SJed Brown Mat J; 44456044e6dSMatthew G. Knepley const PetscScalar *coords; 44556044e6dSMatthew G. Knepley PetscScalar *a; 446de73a395SMatthew G. Knepley PetscInt Nf, p; 4475509d985SMatthew G. Knepley const PetscInt dof = ctx->dof; 448552f7358SJed Brown PetscErrorCode ierr; 449552f7358SJed Brown 450552f7358SJed Brown PetscFunctionBegin; 451de73a395SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 452de73a395SMatthew G. Knepley if (Nf) {ierr = DMGetField(dm, 0, (PetscObject *) &fem);CHKERRQ(ierr);} 453552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 454fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 455552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 456552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr); 457552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 458552f7358SJed Brown ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr); 459c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 460552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 461552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 462552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 463552f7358SJed Brown ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr); 464552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 465552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 4660298fd71SBarry Smith ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr); 4670298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr); 468552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 469552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 470552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 471552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 472552f7358SJed Brown 47356044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 474552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 475552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 476a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 477552f7358SJed Brown PetscScalar *xi; 478cb313848SJed Brown PetscReal xir[2]; 479552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 480552f7358SJed Brown 481552f7358SJed Brown /* Can make this do all points at once */ 4820298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 4830adebc6cSBarry Smith if (4*2 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %d should be %d", coordSize, 4*2); 4840298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 4850298fd71SBarry Smith ierr = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 4860298fd71SBarry Smith ierr = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 487552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 488552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 489552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 490552f7358SJed Brown ierr = VecRestoreArray(real, &xi);CHKERRQ(ierr); 491552f7358SJed Brown ierr = SNESSolve(snes, real, ref);CHKERRQ(ierr); 492552f7358SJed Brown ierr = VecGetArray(ref, &xi);CHKERRQ(ierr); 493cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 494cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 4955509d985SMatthew G. Knepley if (4*dof != xSize) { 4965509d985SMatthew G. Knepley PetscReal *B; 4975509d985SMatthew G. Knepley PetscInt d; 4981aa26658SKarl Rupp 4995509d985SMatthew G. Knepley xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0; 5005509d985SMatthew G. Knepley ierr = PetscFEGetTabulation(fem, 1, xir, &B, NULL, NULL);CHKERRQ(ierr); 5015509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) { 5025509d985SMatthew G. Knepley a[p*dof+comp] = 0.0; 5035509d985SMatthew G. Knepley for (d = 0; d < xSize/dof; ++d) { 5045509d985SMatthew G. Knepley a[p*dof+comp] += x[d*dof+comp]*B[d*dof+comp]; 5055509d985SMatthew G. Knepley } 5065509d985SMatthew G. Knepley } 5075509d985SMatthew G. Knepley ierr = PetscFERestoreTabulation(fem, 1, xir, &B, NULL, NULL);CHKERRQ(ierr); 5085509d985SMatthew G. Knepley } else { 5095509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) 5105509d985SMatthew G. Knepley 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]; 5115509d985SMatthew G. Knepley } 512552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 5130298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 5140298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 515552f7358SJed Brown } 516552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 51756044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 518552f7358SJed Brown 519552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 520552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 521552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 522552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 523552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 524552f7358SJed Brown PetscFunctionReturn(0); 525552f7358SJed Brown } 526552f7358SJed Brown 5275820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 528552f7358SJed Brown { 529552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 530552f7358SJed Brown const PetscScalar x0 = vertices[0]; 531552f7358SJed Brown const PetscScalar y0 = vertices[1]; 532552f7358SJed Brown const PetscScalar z0 = vertices[2]; 5337a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 5347a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 5357a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 536552f7358SJed Brown const PetscScalar x2 = vertices[6]; 537552f7358SJed Brown const PetscScalar y2 = vertices[7]; 538552f7358SJed Brown const PetscScalar z2 = vertices[8]; 5397a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 5407a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 5417a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 542552f7358SJed Brown const PetscScalar x4 = vertices[12]; 543552f7358SJed Brown const PetscScalar y4 = vertices[13]; 544552f7358SJed Brown const PetscScalar z4 = vertices[14]; 545552f7358SJed Brown const PetscScalar x5 = vertices[15]; 546552f7358SJed Brown const PetscScalar y5 = vertices[16]; 547552f7358SJed Brown const PetscScalar z5 = vertices[17]; 548552f7358SJed Brown const PetscScalar x6 = vertices[18]; 549552f7358SJed Brown const PetscScalar y6 = vertices[19]; 550552f7358SJed Brown const PetscScalar z6 = vertices[20]; 551552f7358SJed Brown const PetscScalar x7 = vertices[21]; 552552f7358SJed Brown const PetscScalar y7 = vertices[22]; 553552f7358SJed Brown const PetscScalar z7 = vertices[23]; 554552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 555552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 556552f7358SJed Brown const PetscScalar h_1 = z1 - z0; 557552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 558552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 559552f7358SJed Brown const PetscScalar h_3 = z3 - z0; 560552f7358SJed Brown const PetscScalar f_4 = x4 - x0; 561552f7358SJed Brown const PetscScalar g_4 = y4 - y0; 562552f7358SJed Brown const PetscScalar h_4 = z4 - z0; 563552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 564552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 565552f7358SJed Brown const PetscScalar h_01 = z2 - z1 - z3 + z0; 566552f7358SJed Brown const PetscScalar f_12 = x7 - x3 - x4 + x0; 567552f7358SJed Brown const PetscScalar g_12 = y7 - y3 - y4 + y0; 568552f7358SJed Brown const PetscScalar h_12 = z7 - z3 - z4 + z0; 569552f7358SJed Brown const PetscScalar f_02 = x5 - x1 - x4 + x0; 570552f7358SJed Brown const PetscScalar g_02 = y5 - y1 - y4 + y0; 571552f7358SJed Brown const PetscScalar h_02 = z5 - z1 - z4 + z0; 572552f7358SJed Brown const PetscScalar f_012 = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 573552f7358SJed Brown const PetscScalar g_012 = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 574552f7358SJed Brown const PetscScalar h_012 = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 57556044e6dSMatthew G. Knepley const PetscScalar *ref; 57656044e6dSMatthew G. Knepley PetscScalar *real; 577552f7358SJed Brown PetscErrorCode ierr; 578552f7358SJed Brown 579552f7358SJed Brown PetscFunctionBegin; 58056044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 581552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 582552f7358SJed Brown { 583552f7358SJed Brown const PetscScalar p0 = ref[0]; 584552f7358SJed Brown const PetscScalar p1 = ref[1]; 585552f7358SJed Brown const PetscScalar p2 = ref[2]; 586552f7358SJed Brown 587552f7358SJed Brown 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; 588552f7358SJed Brown 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; 589552f7358SJed Brown 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; 590552f7358SJed Brown } 591552f7358SJed Brown ierr = PetscLogFlops(114);CHKERRQ(ierr); 59256044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 593552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 594552f7358SJed Brown PetscFunctionReturn(0); 595552f7358SJed Brown } 596552f7358SJed Brown 597d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 598552f7358SJed Brown { 599552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 600552f7358SJed Brown const PetscScalar x0 = vertices[0]; 601552f7358SJed Brown const PetscScalar y0 = vertices[1]; 602552f7358SJed Brown const PetscScalar z0 = vertices[2]; 6037a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 6047a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 6057a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 606552f7358SJed Brown const PetscScalar x2 = vertices[6]; 607552f7358SJed Brown const PetscScalar y2 = vertices[7]; 608552f7358SJed Brown const PetscScalar z2 = vertices[8]; 6097a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 6107a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 6117a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 612552f7358SJed Brown const PetscScalar x4 = vertices[12]; 613552f7358SJed Brown const PetscScalar y4 = vertices[13]; 614552f7358SJed Brown const PetscScalar z4 = vertices[14]; 615552f7358SJed Brown const PetscScalar x5 = vertices[15]; 616552f7358SJed Brown const PetscScalar y5 = vertices[16]; 617552f7358SJed Brown const PetscScalar z5 = vertices[17]; 618552f7358SJed Brown const PetscScalar x6 = vertices[18]; 619552f7358SJed Brown const PetscScalar y6 = vertices[19]; 620552f7358SJed Brown const PetscScalar z6 = vertices[20]; 621552f7358SJed Brown const PetscScalar x7 = vertices[21]; 622552f7358SJed Brown const PetscScalar y7 = vertices[22]; 623552f7358SJed Brown const PetscScalar z7 = vertices[23]; 624552f7358SJed Brown const PetscScalar f_xy = x2 - x1 - x3 + x0; 625552f7358SJed Brown const PetscScalar g_xy = y2 - y1 - y3 + y0; 626552f7358SJed Brown const PetscScalar h_xy = z2 - z1 - z3 + z0; 627552f7358SJed Brown const PetscScalar f_yz = x7 - x3 - x4 + x0; 628552f7358SJed Brown const PetscScalar g_yz = y7 - y3 - y4 + y0; 629552f7358SJed Brown const PetscScalar h_yz = z7 - z3 - z4 + z0; 630552f7358SJed Brown const PetscScalar f_xz = x5 - x1 - x4 + x0; 631552f7358SJed Brown const PetscScalar g_xz = y5 - y1 - y4 + y0; 632552f7358SJed Brown const PetscScalar h_xz = z5 - z1 - z4 + z0; 633552f7358SJed Brown const PetscScalar f_xyz = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 634552f7358SJed Brown const PetscScalar g_xyz = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 635552f7358SJed Brown const PetscScalar h_xyz = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 63656044e6dSMatthew G. Knepley const PetscScalar *ref; 637552f7358SJed Brown PetscErrorCode ierr; 638552f7358SJed Brown 639552f7358SJed Brown PetscFunctionBegin; 64056044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 641552f7358SJed Brown { 642552f7358SJed Brown const PetscScalar x = ref[0]; 643552f7358SJed Brown const PetscScalar y = ref[1]; 644552f7358SJed Brown const PetscScalar z = ref[2]; 645552f7358SJed Brown const PetscInt rows[3] = {0, 1, 2}; 646da80777bSKarl Rupp PetscScalar values[9]; 647da80777bSKarl Rupp 648da80777bSKarl Rupp values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0; 649da80777bSKarl Rupp values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0; 650da80777bSKarl Rupp values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0; 651da80777bSKarl Rupp values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0; 652da80777bSKarl Rupp values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0; 653da80777bSKarl Rupp values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0; 654da80777bSKarl Rupp values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0; 655da80777bSKarl Rupp values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0; 656da80777bSKarl Rupp values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0; 6571aa26658SKarl Rupp 65894ab13aaSBarry Smith ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr); 659552f7358SJed Brown } 660552f7358SJed Brown ierr = PetscLogFlops(152);CHKERRQ(ierr); 66156044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 66294ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 66394ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 664552f7358SJed Brown PetscFunctionReturn(0); 665552f7358SJed Brown } 666552f7358SJed Brown 667a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 668a6dfd86eSKarl Rupp { 669fafc0619SMatthew G Knepley DM dmCoord; 670552f7358SJed Brown SNES snes; 671552f7358SJed Brown KSP ksp; 672552f7358SJed Brown PC pc; 673552f7358SJed Brown Vec coordsLocal, r, ref, real; 674552f7358SJed Brown Mat J; 67556044e6dSMatthew G. Knepley const PetscScalar *coords; 67656044e6dSMatthew G. Knepley PetscScalar *a; 677552f7358SJed Brown PetscInt p; 678552f7358SJed Brown PetscErrorCode ierr; 679552f7358SJed Brown 680552f7358SJed Brown PetscFunctionBegin; 681552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 682fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 683552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 684552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr); 685552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 686552f7358SJed Brown ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr); 687c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 688552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 689552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 690552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 691552f7358SJed Brown ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr); 692552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 693552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 6940298fd71SBarry Smith ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr); 6950298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr); 696552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 697552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 698552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 699552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 700552f7358SJed Brown 70156044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 702552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 703552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 704a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 705552f7358SJed Brown PetscScalar *xi; 706cb313848SJed Brown PetscReal xir[3]; 707552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 708552f7358SJed Brown 709552f7358SJed Brown /* Can make this do all points at once */ 7100298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 7110adebc6cSBarry Smith if (8*3 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %d should be %d", coordSize, 8*3); 7120298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 7130adebc6cSBarry Smith if (8*ctx->dof != xSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %d should be %d", xSize, 8*ctx->dof); 7140298fd71SBarry Smith ierr = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 7150298fd71SBarry Smith ierr = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 716552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 717552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 718552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 719552f7358SJed Brown xi[2] = coords[p*ctx->dim+2]; 720552f7358SJed Brown ierr = VecRestoreArray(real, &xi);CHKERRQ(ierr); 721552f7358SJed Brown ierr = SNESSolve(snes, real, ref);CHKERRQ(ierr); 722552f7358SJed Brown ierr = VecGetArray(ref, &xi);CHKERRQ(ierr); 723cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 724cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 725cb313848SJed Brown xir[2] = PetscRealPart(xi[2]); 726552f7358SJed Brown for (comp = 0; comp < ctx->dof; ++comp) { 727552f7358SJed Brown a[p*ctx->dof+comp] = 728cb313848SJed Brown x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) + 7297a1931ceSMatthew G. Knepley x[3*ctx->dof+comp]* xir[0]*(1-xir[1])*(1-xir[2]) + 730cb313848SJed Brown x[2*ctx->dof+comp]* xir[0]* xir[1]*(1-xir[2]) + 7317a1931ceSMatthew G. Knepley x[1*ctx->dof+comp]*(1-xir[0])* xir[1]*(1-xir[2]) + 732cb313848SJed Brown x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])* xir[2] + 733cb313848SJed Brown x[5*ctx->dof+comp]* xir[0]*(1-xir[1])* xir[2] + 734cb313848SJed Brown x[6*ctx->dof+comp]* xir[0]* xir[1]* xir[2] + 735cb313848SJed Brown x[7*ctx->dof+comp]*(1-xir[0])* xir[1]* xir[2]; 736552f7358SJed Brown } 737552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 7380298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 7390298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 740552f7358SJed Brown } 741552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 74256044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 743552f7358SJed Brown 744552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 745552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 746552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 747552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 748552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 749552f7358SJed Brown PetscFunctionReturn(0); 750552f7358SJed Brown } 751552f7358SJed Brown 752552f7358SJed Brown /* 753552f7358SJed Brown Input Parameters: 754552f7358SJed Brown + ctx - The DMInterpolationInfo context 755552f7358SJed Brown . dm - The DM 756552f7358SJed Brown - x - The local vector containing the field to be interpolated 757552f7358SJed Brown 758552f7358SJed Brown Output Parameters: 759552f7358SJed Brown . v - The vector containing the interpolated values 760552f7358SJed Brown */ 7610adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v) 7620adebc6cSBarry Smith { 763552f7358SJed Brown PetscInt dim, coneSize, n; 764552f7358SJed Brown PetscErrorCode ierr; 765552f7358SJed Brown 766552f7358SJed Brown PetscFunctionBegin; 767552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 768552f7358SJed Brown PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 769552f7358SJed Brown PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 770552f7358SJed Brown ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr); 7710adebc6cSBarry Smith if (n != ctx->n*ctx->dof) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %d should be %d", n, ctx->n*ctx->dof); 772552f7358SJed Brown if (n) { 773c73cfb54SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 774552f7358SJed Brown ierr = DMPlexGetConeSize(dm, ctx->cells[0], &coneSize);CHKERRQ(ierr); 775552f7358SJed Brown if (dim == 2) { 776552f7358SJed Brown if (coneSize == 3) { 7777a1931ceSMatthew G. Knepley ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr); 778552f7358SJed Brown } else if (coneSize == 4) { 779552f7358SJed Brown ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr); 7800adebc6cSBarry Smith } else SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dimension %d for point interpolation", dim); 781552f7358SJed Brown } else if (dim == 3) { 782552f7358SJed Brown if (coneSize == 4) { 7837a1931ceSMatthew G. Knepley ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr); 784552f7358SJed Brown } else { 785552f7358SJed Brown ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr); 786552f7358SJed Brown } 7870adebc6cSBarry Smith } else SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Unsupported dimension %d for point interpolation", dim); 788552f7358SJed Brown } 789552f7358SJed Brown PetscFunctionReturn(0); 790552f7358SJed Brown } 791552f7358SJed Brown 7920adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx) 7930adebc6cSBarry Smith { 794552f7358SJed Brown PetscErrorCode ierr; 795552f7358SJed Brown 796552f7358SJed Brown PetscFunctionBegin; 797552f7358SJed Brown PetscValidPointer(ctx, 2); 798552f7358SJed Brown ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr); 799552f7358SJed Brown ierr = PetscFree((*ctx)->points);CHKERRQ(ierr); 800552f7358SJed Brown ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr); 801552f7358SJed Brown ierr = PetscFree(*ctx);CHKERRQ(ierr); 8020298fd71SBarry Smith *ctx = NULL; 803552f7358SJed Brown PetscFunctionReturn(0); 804552f7358SJed Brown } 805cc0c4584SMatthew G. Knepley 806cc0c4584SMatthew G. Knepley /*@C 807cc0c4584SMatthew G. Knepley SNESMonitorFields - Monitors the residual for each field separately 808cc0c4584SMatthew G. Knepley 809cc0c4584SMatthew G. Knepley Collective on SNES 810cc0c4584SMatthew G. Knepley 811cc0c4584SMatthew G. Knepley Input Parameters: 812cc0c4584SMatthew G. Knepley + snes - the SNES context 813cc0c4584SMatthew G. Knepley . its - iteration number 814cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual 815d43b4f6eSBarry Smith - vf - PetscViewerAndFormat of type ASCII 816cc0c4584SMatthew G. Knepley 817cc0c4584SMatthew G. Knepley Notes: 818cc0c4584SMatthew G. Knepley This routine prints the residual norm at each iteration. 819cc0c4584SMatthew G. Knepley 820cc0c4584SMatthew G. Knepley Level: intermediate 821cc0c4584SMatthew G. Knepley 822cc0c4584SMatthew G. Knepley .keywords: SNES, nonlinear, default, monitor, norm 823cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault() 824cc0c4584SMatthew G. Knepley @*/ 825d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 826cc0c4584SMatthew G. Knepley { 827d43b4f6eSBarry Smith PetscViewer viewer = vf->viewer; 828cc0c4584SMatthew G. Knepley Vec res; 829cc0c4584SMatthew G. Knepley DM dm; 830cc0c4584SMatthew G. Knepley PetscSection s; 831cc0c4584SMatthew G. Knepley const PetscScalar *r; 832cc0c4584SMatthew G. Knepley PetscReal *lnorms, *norms; 833cc0c4584SMatthew G. Knepley PetscInt numFields, f, pStart, pEnd, p; 834cc0c4584SMatthew G. Knepley PetscErrorCode ierr; 835cc0c4584SMatthew G. Knepley 836cc0c4584SMatthew G. Knepley PetscFunctionBegin; 8374d4332d5SBarry Smith PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 838cc0c4584SMatthew G. Knepley ierr = SNESGetFunction(snes, &res, 0, 0);CHKERRQ(ierr); 839cc0c4584SMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 840cc0c4584SMatthew G. Knepley ierr = DMGetDefaultSection(dm, &s);CHKERRQ(ierr); 841cc0c4584SMatthew G. Knepley ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr); 842cc0c4584SMatthew G. Knepley ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 843cc0c4584SMatthew G. Knepley ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr); 844cc0c4584SMatthew G. Knepley ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr); 845cc0c4584SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 846cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 847cc0c4584SMatthew G. Knepley PetscInt fdof, foff, d; 848cc0c4584SMatthew G. Knepley 849cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr); 850cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr); 851cc0c4584SMatthew G. Knepley for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d])); 852cc0c4584SMatthew G. Knepley } 853cc0c4584SMatthew G. Knepley } 854cc0c4584SMatthew G. Knepley ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr); 855b2566f29SBarry Smith ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 856d43b4f6eSBarry Smith ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 857cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 858cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr); 859cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 860cc0c4584SMatthew G. Knepley if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 861cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr); 862cc0c4584SMatthew G. Knepley } 863cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr); 864cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 865d43b4f6eSBarry Smith ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 866cc0c4584SMatthew G. Knepley ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr); 867cc0c4584SMatthew G. Knepley PetscFunctionReturn(0); 868cc0c4584SMatthew G. Knepley } 86924cdb843SMatthew G. Knepley 87024cdb843SMatthew G. Knepley /********************* Residual Computation **************************/ 87124cdb843SMatthew G. Knepley 8724a3e9fdbSToby Isaac static PetscErrorCode PetscContainerUserDestroy_PetscFEGeom (void *ctx) 8737d4028c8SMatthew G. Knepley { 8744a3e9fdbSToby Isaac PetscFEGeom *geom = (PetscFEGeom *) ctx; 8757d4028c8SMatthew G. Knepley PetscErrorCode ierr; 8767d4028c8SMatthew G. Knepley 8777d4028c8SMatthew G. Knepley PetscFunctionBegin; 8784a3e9fdbSToby Isaac ierr = PetscFEGeomDestroy(&geom);CHKERRQ(ierr); 8794a3e9fdbSToby Isaac PetscFunctionReturn(0); 8807d4028c8SMatthew G. Knepley } 8814a3e9fdbSToby Isaac 8824a3e9fdbSToby Isaac static PetscErrorCode DMSNESGetFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom) 8834a3e9fdbSToby Isaac { 8844a3e9fdbSToby Isaac char composeStr[33] = {0}; 8854a3e9fdbSToby Isaac PetscObjectId id; 8864a3e9fdbSToby Isaac PetscContainer container; 8874a3e9fdbSToby Isaac PetscErrorCode ierr; 8884a3e9fdbSToby Isaac 8894a3e9fdbSToby Isaac PetscFunctionBegin; 8904a3e9fdbSToby Isaac ierr = PetscObjectGetId((PetscObject)quad,&id);CHKERRQ(ierr); 8914a3e9fdbSToby Isaac ierr = PetscSNPrintf(composeStr, 32, "DMSNESGetFEGeom_%x\n", id);CHKERRQ(ierr); 8924a3e9fdbSToby Isaac ierr = PetscObjectQuery((PetscObject) pointIS, composeStr, (PetscObject *) &container);CHKERRQ(ierr); 8934a3e9fdbSToby Isaac if (container) { 8944a3e9fdbSToby Isaac ierr = PetscContainerGetPointer(container, (void **) geom);CHKERRQ(ierr); 8954a3e9fdbSToby Isaac } else { 8964a3e9fdbSToby Isaac ierr = DMFieldCreateFEGeom(coordField, pointIS, quad, faceData, geom);CHKERRQ(ierr); 8974a3e9fdbSToby Isaac ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr); 8984a3e9fdbSToby Isaac ierr = PetscContainerSetPointer(container, (void *) *geom);CHKERRQ(ierr); 8994a3e9fdbSToby Isaac ierr = PetscContainerSetUserDestroy(container, PetscContainerUserDestroy_PetscFEGeom);CHKERRQ(ierr); 9004a3e9fdbSToby Isaac ierr = PetscObjectCompose((PetscObject) pointIS, composeStr, (PetscObject) container);CHKERRQ(ierr); 9014a3e9fdbSToby Isaac ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 9024a3e9fdbSToby Isaac } 9034a3e9fdbSToby Isaac PetscFunctionReturn(0); 9044a3e9fdbSToby Isaac } 9054a3e9fdbSToby Isaac 9064a3e9fdbSToby Isaac static PetscErrorCode DMSNESRestoreFEGeom(DMField coordField, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom) 9074a3e9fdbSToby Isaac { 9084a3e9fdbSToby Isaac PetscFunctionBegin; 9094a3e9fdbSToby Isaac *geom = NULL; 9107d4028c8SMatthew G. Knepley PetscFunctionReturn(0); 9117d4028c8SMatthew G. Knepley } 9127d4028c8SMatthew G. Knepley 91308449791SMatthew G. Knepley /*@ 91408449791SMatthew G. Knepley DMPlexSNESGetGeometryFVM - Return precomputed geometric data 91508449791SMatthew G. Knepley 91608449791SMatthew G. Knepley Input Parameter: 91708449791SMatthew G. Knepley . dm - The DM 91808449791SMatthew G. Knepley 91908449791SMatthew G. Knepley Output Parameters: 92008449791SMatthew G. Knepley + facegeom - The values precomputed from face geometry 92108449791SMatthew G. Knepley . cellgeom - The values precomputed from cell geometry 92208449791SMatthew G. Knepley - minRadius - The minimum radius over the mesh of an inscribed sphere in a cell 92308449791SMatthew G. Knepley 92408449791SMatthew G. Knepley Level: developer 92508449791SMatthew G. Knepley 92608449791SMatthew G. Knepley .seealso: DMPlexTSSetRHSFunctionLocal() 92708449791SMatthew G. Knepley @*/ 92808449791SMatthew G. Knepley PetscErrorCode DMPlexSNESGetGeometryFVM(DM dm, Vec *facegeom, Vec *cellgeom, PetscReal *minRadius) 92924cdb843SMatthew G. Knepley { 9304b32e5bbSToby Isaac DM plex; 93124cdb843SMatthew G. Knepley PetscErrorCode ierr; 93224cdb843SMatthew G. Knepley 93324cdb843SMatthew G. Knepley PetscFunctionBegin; 93408449791SMatthew G. Knepley PetscValidHeaderSpecific(dm,DM_CLASSID,1); 9354b32e5bbSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 9364b32e5bbSToby Isaac ierr = DMPlexGetDataFVM(plex, NULL, cellgeom, facegeom, NULL);CHKERRQ(ierr); 9374b32e5bbSToby Isaac if (minRadius) {ierr = DMPlexGetMinRadius(plex, minRadius);CHKERRQ(ierr);} 9384b32e5bbSToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 93924cdb843SMatthew G. Knepley PetscFunctionReturn(0); 94024cdb843SMatthew G. Knepley } 94124cdb843SMatthew G. Knepley 942dbd489d2SMatthew G. Knepley /*@ 94308449791SMatthew G. Knepley DMPlexSNESGetGradientDM - Return gradient data layout 94408449791SMatthew G. Knepley 94508449791SMatthew G. Knepley Input Parameters: 94608449791SMatthew G. Knepley + dm - The DM 94708449791SMatthew G. Knepley - fv - The PetscFV 94808449791SMatthew G. Knepley 94908449791SMatthew G. Knepley Output Parameter: 95008449791SMatthew G. Knepley . dmGrad - The layout for gradient values 95108449791SMatthew G. Knepley 95208449791SMatthew G. Knepley Level: developer 95308449791SMatthew G. Knepley 95408449791SMatthew G. Knepley .seealso: DMPlexSNESGetGeometryFVM() 95508449791SMatthew G. Knepley @*/ 95608449791SMatthew G. Knepley PetscErrorCode DMPlexSNESGetGradientDM(DM dm, PetscFV fv, DM *dmGrad) 95724cdb843SMatthew G. Knepley { 9584b32e5bbSToby Isaac DM plex; 95908449791SMatthew G. Knepley PetscBool computeGradients; 96024cdb843SMatthew G. Knepley PetscErrorCode ierr; 96124cdb843SMatthew G. Knepley 96224cdb843SMatthew G. Knepley PetscFunctionBegin; 96308449791SMatthew G. Knepley PetscValidHeaderSpecific(dm,DM_CLASSID,1); 96408449791SMatthew G. Knepley PetscValidHeaderSpecific(fv,PETSCFV_CLASSID,2); 96508449791SMatthew G. Knepley PetscValidPointer(dmGrad,3); 96608449791SMatthew G. Knepley ierr = PetscFVGetComputeGradients(fv, &computeGradients);CHKERRQ(ierr); 96708449791SMatthew G. Knepley if (!computeGradients) {*dmGrad = NULL; PetscFunctionReturn(0);} 9684b32e5bbSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 9694b32e5bbSToby Isaac ierr = DMPlexGetDataFVM(plex, fv, NULL, NULL, dmGrad);CHKERRQ(ierr); 9704b32e5bbSToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 97108449791SMatthew G. Knepley PetscFunctionReturn(0); 97208449791SMatthew G. Knepley } 97308449791SMatthew G. Knepley 97408449791SMatthew G. Knepley /*@C 97508449791SMatthew G. Knepley DMPlexGetCellFields - Retrieve the field values values for a chunk of cells 97608449791SMatthew G. Knepley 97708449791SMatthew G. Knepley Input Parameters: 97808449791SMatthew G. Knepley + dm - The DM 9799044fa66SMatthew G. Knepley . cellIS - The cells to include 98008449791SMatthew G. Knepley . locX - A local vector with the solution fields 98108449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL 98208449791SMatthew G. Knepley - locA - A local vector with auxiliary fields, or NULL 98308449791SMatthew G. Knepley 98408449791SMatthew G. Knepley Output Parameters: 98508449791SMatthew G. Knepley + u - The field coefficients 98608449791SMatthew G. Knepley . u_t - The fields derivative coefficients 98708449791SMatthew G. Knepley - a - The auxiliary field coefficients 98808449791SMatthew G. Knepley 98908449791SMatthew G. Knepley Level: developer 99008449791SMatthew G. Knepley 99108449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields() 99208449791SMatthew G. Knepley @*/ 9939044fa66SMatthew G. Knepley PetscErrorCode DMPlexGetCellFields(DM dm, IS cellIS, Vec locX, Vec locX_t, Vec locA, PetscScalar **u, PetscScalar **u_t, PetscScalar **a) 99408449791SMatthew G. Knepley { 9959044fa66SMatthew G. Knepley DM plex, plexA = NULL; 99608449791SMatthew G. Knepley PetscSection section, sectionAux; 99708449791SMatthew G. Knepley PetscDS prob; 9989044fa66SMatthew G. Knepley const PetscInt *cells; 9999044fa66SMatthew G. Knepley PetscInt cStart, cEnd, numCells, totDim, totDimAux, c; 100008449791SMatthew G. Knepley PetscErrorCode ierr; 100108449791SMatthew G. Knepley 100208449791SMatthew G. Knepley PetscFunctionBegin; 100308449791SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100408449791SMatthew G. Knepley PetscValidHeaderSpecific(locX, VEC_CLASSID, 4); 100508449791SMatthew G. Knepley if (locX_t) {PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 5);} 100608449791SMatthew G. Knepley if (locA) {PetscValidHeaderSpecific(locA, VEC_CLASSID, 6);} 100708449791SMatthew G. Knepley PetscValidPointer(u, 7); 100808449791SMatthew G. Knepley PetscValidPointer(u_t, 8); 100908449791SMatthew G. Knepley PetscValidPointer(a, 9); 10109044fa66SMatthew G. Knepley ierr = DMSNESConvertPlex(dm, &plex, PETSC_FALSE);CHKERRQ(ierr); 10119044fa66SMatthew G. Knepley ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 101224cdb843SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 101324cdb843SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 101424cdb843SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 101508449791SMatthew G. Knepley if (locA) { 10169044fa66SMatthew G. Knepley DM dmAux; 101708449791SMatthew G. Knepley PetscDS probAux; 101808449791SMatthew G. Knepley 101908449791SMatthew G. Knepley ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr); 10209044fa66SMatthew G. Knepley ierr = DMSNESConvertPlex(dmAux, &plexA, PETSC_FALSE);CHKERRQ(ierr); 102124cdb843SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 102224cdb843SMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 102324cdb843SMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 102424cdb843SMatthew G. Knepley } 10259044fa66SMatthew G. Knepley numCells = cEnd - cStart; 102669291d52SBarry Smith ierr = DMGetWorkArray(dm, numCells*totDim, MPIU_SCALAR, u);CHKERRQ(ierr); 102769291d52SBarry Smith if (locX_t) {ierr = DMGetWorkArray(dm, numCells*totDim, MPIU_SCALAR, u_t);CHKERRQ(ierr);} else {*u_t = NULL;} 102869291d52SBarry Smith if (locA) {ierr = DMGetWorkArray(dm, numCells*totDimAux, MPIU_SCALAR, a);CHKERRQ(ierr);} else {*a = NULL;} 102924cdb843SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 10309044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 10319044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 103208449791SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL, *ul = *u, *ul_t = *u_t, *al = *a; 103324cdb843SMatthew G. Knepley PetscInt i; 103424cdb843SMatthew G. Knepley 10359044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(plex, section, locX, cell, NULL, &x);CHKERRQ(ierr); 10369044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) ul[cind*totDim+i] = x[i]; 10379044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plex, section, locX, cell, NULL, &x);CHKERRQ(ierr); 103808449791SMatthew G. Knepley if (locX_t) { 10399044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(plex, section, locX_t, cell, NULL, &x_t);CHKERRQ(ierr); 10409044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) ul_t[cind*totDim+i] = x_t[i]; 10419044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plex, section, locX_t, cell, NULL, &x_t);CHKERRQ(ierr); 104224cdb843SMatthew G. Knepley } 104308449791SMatthew G. Knepley if (locA) { 10449044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(plexA, sectionAux, locA, cell, NULL, &x);CHKERRQ(ierr); 10459044fa66SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) al[cind*totDimAux+i] = x[i]; 10469044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plexA, sectionAux, locA, cell, NULL, &x);CHKERRQ(ierr); 104724cdb843SMatthew G. Knepley } 104824cdb843SMatthew G. Knepley } 10499044fa66SMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 10509044fa66SMatthew G. Knepley if (locA) {ierr = DMDestroy(&plexA);CHKERRQ(ierr);} 10519044fa66SMatthew G. Knepley ierr = ISRestorePointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 105208449791SMatthew G. Knepley PetscFunctionReturn(0); 105308449791SMatthew G. Knepley } 105424cdb843SMatthew G. Knepley 105508449791SMatthew G. Knepley /*@C 105608449791SMatthew G. Knepley DMPlexRestoreCellFields - Restore the field values values for a chunk of cells 105708449791SMatthew G. Knepley 105808449791SMatthew G. Knepley Input Parameters: 105908449791SMatthew G. Knepley + dm - The DM 10609044fa66SMatthew G. Knepley . cellIS - The cells to include 106108449791SMatthew G. Knepley . locX - A local vector with the solution fields 106208449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL 106308449791SMatthew G. Knepley - locA - A local vector with auxiliary fields, or NULL 106408449791SMatthew G. Knepley 106508449791SMatthew G. Knepley Output Parameters: 106608449791SMatthew G. Knepley + u - The field coefficients 106708449791SMatthew G. Knepley . u_t - The fields derivative coefficients 106808449791SMatthew G. Knepley - a - The auxiliary field coefficients 106908449791SMatthew G. Knepley 107008449791SMatthew G. Knepley Level: developer 107108449791SMatthew G. Knepley 107208449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields() 107308449791SMatthew G. Knepley @*/ 10749044fa66SMatthew G. Knepley PetscErrorCode DMPlexRestoreCellFields(DM dm, IS cellIS, Vec locX, Vec locX_t, Vec locA, PetscScalar **u, PetscScalar **u_t, PetscScalar **a) 107508449791SMatthew G. Knepley { 107608449791SMatthew G. Knepley PetscErrorCode ierr; 107708449791SMatthew G. Knepley 107808449791SMatthew G. Knepley PetscFunctionBegin; 107969291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, u);CHKERRQ(ierr); 1080040f60c8SVaclav Hapla if (locX_t) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, u_t);CHKERRQ(ierr);} 1081040f60c8SVaclav Hapla if (locA) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, a);CHKERRQ(ierr);} 108208449791SMatthew G. Knepley PetscFunctionReturn(0); 108324cdb843SMatthew G. Knepley } 108408449791SMatthew G. Knepley 108508449791SMatthew G. Knepley /*@C 108608449791SMatthew G. Knepley DMPlexGetFaceFields - Retrieve the field values values for a chunk of faces 108708449791SMatthew G. Knepley 108808449791SMatthew G. Knepley Input Parameters: 108908449791SMatthew G. Knepley + dm - The DM 109008449791SMatthew G. Knepley . fStart - The first face to include 109108449791SMatthew G. Knepley . fEnd - The first face to exclude 109208449791SMatthew G. Knepley . locX - A local vector with the solution fields 109308449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL 109408449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry 109508449791SMatthew G. Knepley . cellGeometry - A local vector with cell geometry 109608449791SMatthew G. Knepley - locaGrad - A local vector with field gradients, or NULL 109708449791SMatthew G. Knepley 109808449791SMatthew G. Knepley Output Parameters: 10995f942ad5SMatthew G. Knepley + Nface - The number of faces with field values 11005f942ad5SMatthew G. Knepley . uL - The field values at the left side of the face 1101477f7dfdSMatthew G. Knepley - uR - The field values at the right side of the face 110208449791SMatthew G. Knepley 110308449791SMatthew G. Knepley Level: developer 110408449791SMatthew G. Knepley 110508449791SMatthew G. Knepley .seealso: DMPlexGetCellFields() 110608449791SMatthew G. Knepley @*/ 11075f942ad5SMatthew G. Knepley PetscErrorCode DMPlexGetFaceFields(DM dm, PetscInt fStart, PetscInt fEnd, Vec locX, Vec locX_t, Vec faceGeometry, Vec cellGeometry, Vec locGrad, PetscInt *Nface, PetscScalar **uL, PetscScalar **uR) 110808449791SMatthew G. Knepley { 110908449791SMatthew G. Knepley DM dmFace, dmCell, dmGrad = NULL; 1110195142f5SMatthew G. Knepley PetscSection section; 111108449791SMatthew G. Knepley PetscDS prob; 111208449791SMatthew G. Knepley DMLabel ghostLabel; 111308449791SMatthew G. Knepley const PetscScalar *facegeom, *cellgeom, *x, *lgrad; 1114477f7dfdSMatthew G. Knepley PetscBool *isFE; 1115477f7dfdSMatthew G. Knepley PetscInt dim, Nf, f, Nc, numFaces = fEnd - fStart, iface, face; 111608449791SMatthew G. Knepley PetscErrorCode ierr; 111708449791SMatthew G. Knepley 111808449791SMatthew G. Knepley PetscFunctionBegin; 111908449791SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 112008449791SMatthew G. Knepley PetscValidHeaderSpecific(locX, VEC_CLASSID, 4); 112108449791SMatthew G. Knepley if (locX_t) {PetscValidHeaderSpecific(locX_t, VEC_CLASSID, 5);} 112208449791SMatthew G. Knepley PetscValidHeaderSpecific(faceGeometry, VEC_CLASSID, 6); 112308449791SMatthew G. Knepley PetscValidHeaderSpecific(cellGeometry, VEC_CLASSID, 7); 112408449791SMatthew G. Knepley if (locGrad) {PetscValidHeaderSpecific(locGrad, VEC_CLASSID, 8);} 112508449791SMatthew G. Knepley PetscValidPointer(uL, 9); 112608449791SMatthew G. Knepley PetscValidPointer(uR, 10); 112708449791SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 112808449791SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 1129195142f5SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1130477f7dfdSMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 1131477f7dfdSMatthew G. Knepley ierr = PetscDSGetTotalComponents(prob, &Nc);CHKERRQ(ierr); 1132477f7dfdSMatthew G. Knepley ierr = PetscMalloc1(Nf, &isFE);CHKERRQ(ierr); 1133477f7dfdSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1134477f7dfdSMatthew G. Knepley PetscObject obj; 1135477f7dfdSMatthew G. Knepley PetscClassId id; 1136477f7dfdSMatthew G. Knepley 11374a270516SSander Arens ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1138477f7dfdSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1139477f7dfdSMatthew G. Knepley if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 1140477f7dfdSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 1141477f7dfdSMatthew G. Knepley else {isFE[f] = PETSC_FALSE;} 1142477f7dfdSMatthew G. Knepley } 1143c58f1c22SToby Isaac ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); 114408449791SMatthew G. Knepley ierr = VecGetArrayRead(locX, &x);CHKERRQ(ierr); 114508449791SMatthew G. Knepley ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); 114608449791SMatthew G. Knepley ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 114708449791SMatthew G. Knepley ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); 114808449791SMatthew G. Knepley ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 114908449791SMatthew G. Knepley if (locGrad) { 115008449791SMatthew G. Knepley ierr = VecGetDM(locGrad, &dmGrad);CHKERRQ(ierr); 115108449791SMatthew G. Knepley ierr = VecGetArrayRead(locGrad, &lgrad);CHKERRQ(ierr); 115224cdb843SMatthew G. Knepley } 115369291d52SBarry Smith ierr = DMGetWorkArray(dm, numFaces*Nc, MPIU_SCALAR, uL);CHKERRQ(ierr); 115469291d52SBarry Smith ierr = DMGetWorkArray(dm, numFaces*Nc, MPIU_SCALAR, uR);CHKERRQ(ierr); 1155477f7dfdSMatthew G. Knepley /* Right now just eat the extra work for FE (could make a cell loop) */ 115608449791SMatthew G. Knepley for (face = fStart, iface = 0; face < fEnd; ++face) { 115708449791SMatthew G. Knepley const PetscInt *cells; 1158640bce14SSatish Balay PetscFVFaceGeom *fg; 1159640bce14SSatish Balay PetscFVCellGeom *cgL, *cgR; 1160640bce14SSatish Balay PetscScalar *xL, *xR, *gL, *gR; 116108449791SMatthew G. Knepley PetscScalar *uLl = *uL, *uRl = *uR; 11623e64cd2fSToby Isaac PetscInt ghost, nsupp, nchild; 116308449791SMatthew G. Knepley 116408449791SMatthew G. Knepley ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr); 1165e697831aSToby Isaac ierr = DMPlexGetSupportSize(dm, face, &nsupp);CHKERRQ(ierr); 11663e64cd2fSToby Isaac ierr = DMPlexGetTreeChildren(dm, face, &nchild, NULL);CHKERRQ(ierr); 11677c45b140SToby Isaac if (ghost >= 0 || nsupp > 2 || nchild > 0) continue; 116808449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); 116908449791SMatthew G. Knepley ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); 117008449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cgL);CHKERRQ(ierr); 117108449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, cells[1], cellgeom, &cgR);CHKERRQ(ierr); 1172477f7dfdSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1173477f7dfdSMatthew G. Knepley PetscInt off; 1174477f7dfdSMatthew G. Knepley 117537a43ebbSMatthew G. Knepley ierr = PetscDSGetComponentOffset(prob, f, &off);CHKERRQ(ierr); 1176477f7dfdSMatthew G. Knepley if (isFE[f]) { 1177477f7dfdSMatthew G. Knepley const PetscInt *cone; 11783e64cd2fSToby Isaac PetscInt comp, coneSizeL, coneSizeR, faceLocL, faceLocR, ldof, rdof, d; 1179477f7dfdSMatthew G. Knepley 1180cca9989dSMatthew G. Knepley xL = xR = NULL; 11817c45b140SToby Isaac ierr = PetscSectionGetFieldComponents(section, f, &comp);CHKERRQ(ierr); 1182cca9989dSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, locX, cells[0], &ldof, (PetscScalar **) &xL);CHKERRQ(ierr); 1183cca9989dSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, locX, cells[1], &rdof, (PetscScalar **) &xR);CHKERRQ(ierr); 1184477f7dfdSMatthew G. Knepley ierr = DMPlexGetCone(dm, cells[0], &cone);CHKERRQ(ierr); 11853e64cd2fSToby Isaac ierr = DMPlexGetConeSize(dm, cells[0], &coneSizeL);CHKERRQ(ierr); 11863e64cd2fSToby Isaac for (faceLocL = 0; faceLocL < coneSizeL; ++faceLocL) if (cone[faceLocL] == face) break; 1187477f7dfdSMatthew G. Knepley ierr = DMPlexGetCone(dm, cells[1], &cone);CHKERRQ(ierr); 11883e64cd2fSToby Isaac ierr = DMPlexGetConeSize(dm, cells[1], &coneSizeR);CHKERRQ(ierr); 11893e64cd2fSToby Isaac for (faceLocR = 0; faceLocR < coneSizeR; ++faceLocR) if (cone[faceLocR] == face) break; 11903e64cd2fSToby Isaac if (faceLocL == coneSizeL && faceLocR == coneSizeR) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d or cell %d", face, cells[0], cells[1]); 1191195142f5SMatthew G. Knepley /* Check that FEM field has values in the right cell (sometimes its an FV ghost cell) */ 11923e64cd2fSToby Isaac /* TODO: this is a hack that might not be right for nonconforming */ 11933e64cd2fSToby Isaac if (faceLocL < coneSizeL) { 1194477f7dfdSMatthew G. Knepley ierr = EvaluateFaceFields(prob, f, faceLocL, xL, &uLl[iface*Nc+off]);CHKERRQ(ierr); 11953e64cd2fSToby Isaac if (rdof == ldof && faceLocR < coneSizeR) {ierr = EvaluateFaceFields(prob, f, faceLocR, xR, &uRl[iface*Nc+off]);CHKERRQ(ierr);} 11967c45b140SToby Isaac else {for(d = 0; d < comp; ++d) uRl[iface*Nc+off+d] = uLl[iface*Nc+off+d];} 11973e64cd2fSToby Isaac } 11983e64cd2fSToby Isaac else { 11993e64cd2fSToby Isaac ierr = EvaluateFaceFields(prob, f, faceLocR, xR, &uRl[iface*Nc+off]);CHKERRQ(ierr); 12003e64cd2fSToby Isaac ierr = PetscSectionGetFieldComponents(section, f, &comp);CHKERRQ(ierr); 12013e64cd2fSToby Isaac for(d = 0; d < comp; ++d) uLl[iface*Nc+off+d] = uRl[iface*Nc+off+d]; 12023e64cd2fSToby Isaac } 1203cca9989dSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, locX, cells[0], &ldof, (PetscScalar **) &xL);CHKERRQ(ierr); 1204cca9989dSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, locX, cells[1], &rdof, (PetscScalar **) &xR);CHKERRQ(ierr); 1205477f7dfdSMatthew G. Knepley } else { 1206477f7dfdSMatthew G. Knepley PetscFV fv; 1207477f7dfdSMatthew G. Knepley PetscInt numComp, c; 1208477f7dfdSMatthew G. Knepley 1209477f7dfdSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fv);CHKERRQ(ierr); 1210477f7dfdSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &numComp);CHKERRQ(ierr); 1211cca9989dSMatthew G. Knepley ierr = DMPlexPointLocalFieldRead(dm, cells[0], f, x, &xL);CHKERRQ(ierr); 1212cca9989dSMatthew G. Knepley ierr = DMPlexPointLocalFieldRead(dm, cells[1], f, x, &xR);CHKERRQ(ierr); 121308449791SMatthew G. Knepley if (dmGrad) { 121408449791SMatthew G. Knepley PetscReal dxL[3], dxR[3]; 121508449791SMatthew G. Knepley 121608449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmGrad, cells[0], lgrad, &gL);CHKERRQ(ierr); 121708449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmGrad, cells[1], lgrad, &gR);CHKERRQ(ierr); 121808449791SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, cgL->centroid, fg->centroid, dxL); 121908449791SMatthew G. Knepley DMPlex_WaxpyD_Internal(dim, -1, cgR->centroid, fg->centroid, dxR); 1220477f7dfdSMatthew G. Knepley for (c = 0; c < numComp; ++c) { 1221477f7dfdSMatthew G. Knepley uLl[iface*Nc+off+c] = xL[c] + DMPlex_DotD_Internal(dim, &gL[c*dim], dxL); 1222477f7dfdSMatthew G. Knepley uRl[iface*Nc+off+c] = xR[c] + DMPlex_DotD_Internal(dim, &gR[c*dim], dxR); 122308449791SMatthew G. Knepley } 122408449791SMatthew G. Knepley } else { 1225477f7dfdSMatthew G. Knepley for (c = 0; c < numComp; ++c) { 1226477f7dfdSMatthew G. Knepley uLl[iface*Nc+off+c] = xL[c]; 1227477f7dfdSMatthew G. Knepley uRl[iface*Nc+off+c] = xR[c]; 1228477f7dfdSMatthew G. Knepley } 1229477f7dfdSMatthew G. Knepley } 123008449791SMatthew G. Knepley } 123108449791SMatthew G. Knepley } 123208449791SMatthew G. Knepley ++iface; 123308449791SMatthew G. Knepley } 12345f942ad5SMatthew G. Knepley *Nface = iface; 123508449791SMatthew G. Knepley ierr = VecRestoreArrayRead(locX, &x);CHKERRQ(ierr); 123608449791SMatthew G. Knepley ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 123708449791SMatthew G. Knepley ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 123808449791SMatthew G. Knepley if (locGrad) { 123908449791SMatthew G. Knepley ierr = VecRestoreArrayRead(locGrad, &lgrad);CHKERRQ(ierr); 124008449791SMatthew G. Knepley } 1241477f7dfdSMatthew G. Knepley ierr = PetscFree(isFE);CHKERRQ(ierr); 124208449791SMatthew G. Knepley PetscFunctionReturn(0); 124308449791SMatthew G. Knepley } 124408449791SMatthew G. Knepley 124508449791SMatthew G. Knepley /*@C 124608449791SMatthew G. Knepley DMPlexRestoreFaceFields - Restore the field values values for a chunk of faces 124708449791SMatthew G. Knepley 124808449791SMatthew G. Knepley Input Parameters: 124908449791SMatthew G. Knepley + dm - The DM 125008449791SMatthew G. Knepley . fStart - The first face to include 125108449791SMatthew G. Knepley . fEnd - The first face to exclude 125208449791SMatthew G. Knepley . locX - A local vector with the solution fields 125308449791SMatthew G. Knepley . locX_t - A local vector with solution field time derivatives, or NULL 125408449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry 125508449791SMatthew G. Knepley . cellGeometry - A local vector with cell geometry 125608449791SMatthew G. Knepley - locaGrad - A local vector with field gradients, or NULL 125708449791SMatthew G. Knepley 125808449791SMatthew G. Knepley Output Parameters: 12595f942ad5SMatthew G. Knepley + Nface - The number of faces with field values 12605f942ad5SMatthew G. Knepley . uL - The field values at the left side of the face 1261477f7dfdSMatthew G. Knepley - uR - The field values at the right side of the face 126208449791SMatthew G. Knepley 126308449791SMatthew G. Knepley Level: developer 126408449791SMatthew G. Knepley 126508449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields() 126608449791SMatthew G. Knepley @*/ 12675f942ad5SMatthew G. Knepley PetscErrorCode DMPlexRestoreFaceFields(DM dm, PetscInt fStart, PetscInt fEnd, Vec locX, Vec locX_t, Vec faceGeometry, Vec cellGeometry, Vec locGrad, PetscInt *Nface, PetscScalar **uL, PetscScalar **uR) 126808449791SMatthew G. Knepley { 126908449791SMatthew G. Knepley PetscErrorCode ierr; 127008449791SMatthew G. Knepley 127108449791SMatthew G. Knepley PetscFunctionBegin; 127269291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, uL);CHKERRQ(ierr); 127369291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, uR);CHKERRQ(ierr); 127408449791SMatthew G. Knepley PetscFunctionReturn(0); 127508449791SMatthew G. Knepley } 127608449791SMatthew G. Knepley 127708449791SMatthew G. Knepley /*@C 127808449791SMatthew G. Knepley DMPlexGetFaceGeometry - Retrieve the geometric values for a chunk of faces 127908449791SMatthew G. Knepley 128008449791SMatthew G. Knepley Input Parameters: 128108449791SMatthew G. Knepley + dm - The DM 128208449791SMatthew G. Knepley . fStart - The first face to include 128308449791SMatthew G. Knepley . fEnd - The first face to exclude 128408449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry 128508449791SMatthew G. Knepley - cellGeometry - A local vector with cell geometry 128608449791SMatthew G. Knepley 128708449791SMatthew G. Knepley Output Parameters: 12885f942ad5SMatthew G. Knepley + Nface - The number of faces with field values 12895f942ad5SMatthew G. Knepley . fgeom - The extract the face centroid and normal 129008449791SMatthew G. Knepley - vol - The cell volume 129108449791SMatthew G. Knepley 129208449791SMatthew G. Knepley Level: developer 129308449791SMatthew G. Knepley 129408449791SMatthew G. Knepley .seealso: DMPlexGetCellFields() 129508449791SMatthew G. Knepley @*/ 12965f942ad5SMatthew G. Knepley PetscErrorCode DMPlexGetFaceGeometry(DM dm, PetscInt fStart, PetscInt fEnd, Vec faceGeometry, Vec cellGeometry, PetscInt *Nface, PetscFVFaceGeom **fgeom, PetscReal **vol) 129708449791SMatthew G. Knepley { 129808449791SMatthew G. Knepley DM dmFace, dmCell; 129908449791SMatthew G. Knepley DMLabel ghostLabel; 130008449791SMatthew G. Knepley const PetscScalar *facegeom, *cellgeom; 130108449791SMatthew G. Knepley PetscInt dim, numFaces = fEnd - fStart, iface, face; 130208449791SMatthew G. Knepley PetscErrorCode ierr; 130308449791SMatthew G. Knepley 130408449791SMatthew G. Knepley PetscFunctionBegin; 130508449791SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 130608449791SMatthew G. Knepley PetscValidHeaderSpecific(faceGeometry, VEC_CLASSID, 4); 130708449791SMatthew G. Knepley PetscValidHeaderSpecific(cellGeometry, VEC_CLASSID, 5); 130808449791SMatthew G. Knepley PetscValidPointer(fgeom, 6); 130908449791SMatthew G. Knepley PetscValidPointer(vol, 7); 131008449791SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1311c58f1c22SToby Isaac ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); 131208449791SMatthew G. Knepley ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); 131308449791SMatthew G. Knepley ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 131408449791SMatthew G. Knepley ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); 131508449791SMatthew G. Knepley ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 131608449791SMatthew G. Knepley ierr = PetscMalloc1(numFaces, fgeom);CHKERRQ(ierr); 131769291d52SBarry Smith ierr = DMGetWorkArray(dm, numFaces*2, MPIU_SCALAR, vol);CHKERRQ(ierr); 131808449791SMatthew G. Knepley for (face = fStart, iface = 0; face < fEnd; ++face) { 131908449791SMatthew G. Knepley const PetscInt *cells; 1320640bce14SSatish Balay PetscFVFaceGeom *fg; 1321640bce14SSatish Balay PetscFVCellGeom *cgL, *cgR; 132208449791SMatthew G. Knepley PetscFVFaceGeom *fgeoml = *fgeom; 13232eefff9cSMatthew G. Knepley PetscReal *voll = *vol; 13247c45b140SToby Isaac PetscInt ghost, d, nchild, nsupp; 132508449791SMatthew G. Knepley 132608449791SMatthew G. Knepley ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr); 13277c45b140SToby Isaac ierr = DMPlexGetSupportSize(dm, face, &nsupp);CHKERRQ(ierr); 13287c45b140SToby Isaac ierr = DMPlexGetTreeChildren(dm, face, &nchild, NULL);CHKERRQ(ierr); 13297c45b140SToby Isaac if (ghost >= 0 || nsupp > 2 || nchild > 0) continue; 133008449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); 133108449791SMatthew G. Knepley ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); 133208449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cgL);CHKERRQ(ierr); 133308449791SMatthew G. Knepley ierr = DMPlexPointLocalRead(dmCell, cells[1], cellgeom, &cgR);CHKERRQ(ierr); 133408449791SMatthew G. Knepley for (d = 0; d < dim; ++d) { 133508449791SMatthew G. Knepley fgeoml[iface].centroid[d] = fg->centroid[d]; 133608449791SMatthew G. Knepley fgeoml[iface].normal[d] = fg->normal[d]; 133708449791SMatthew G. Knepley } 133808449791SMatthew G. Knepley voll[iface*2+0] = cgL->volume; 133908449791SMatthew G. Knepley voll[iface*2+1] = cgR->volume; 134008449791SMatthew G. Knepley ++iface; 134108449791SMatthew G. Knepley } 13425f942ad5SMatthew G. Knepley *Nface = iface; 134308449791SMatthew G. Knepley ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 134408449791SMatthew G. Knepley ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 134508449791SMatthew G. Knepley PetscFunctionReturn(0); 134608449791SMatthew G. Knepley } 134708449791SMatthew G. Knepley 134808449791SMatthew G. Knepley /*@C 134908449791SMatthew G. Knepley DMPlexRestoreFaceGeometry - Restore the field values values for a chunk of faces 135008449791SMatthew G. Knepley 135108449791SMatthew G. Knepley Input Parameters: 135208449791SMatthew G. Knepley + dm - The DM 135308449791SMatthew G. Knepley . fStart - The first face to include 135408449791SMatthew G. Knepley . fEnd - The first face to exclude 135508449791SMatthew G. Knepley . faceGeometry - A local vector with face geometry 135608449791SMatthew G. Knepley - cellGeometry - A local vector with cell geometry 135708449791SMatthew G. Knepley 135808449791SMatthew G. Knepley Output Parameters: 13595f942ad5SMatthew G. Knepley + Nface - The number of faces with field values 13605f942ad5SMatthew G. Knepley . fgeom - The extract the face centroid and normal 136108449791SMatthew G. Knepley - vol - The cell volume 136208449791SMatthew G. Knepley 136308449791SMatthew G. Knepley Level: developer 136408449791SMatthew G. Knepley 136508449791SMatthew G. Knepley .seealso: DMPlexGetFaceFields() 136608449791SMatthew G. Knepley @*/ 13675f942ad5SMatthew G. Knepley PetscErrorCode DMPlexRestoreFaceGeometry(DM dm, PetscInt fStart, PetscInt fEnd, Vec faceGeometry, Vec cellGeometry, PetscInt *Nface, PetscFVFaceGeom **fgeom, PetscReal **vol) 136808449791SMatthew G. Knepley { 136908449791SMatthew G. Knepley PetscErrorCode ierr; 137008449791SMatthew G. Knepley 137108449791SMatthew G. Knepley PetscFunctionBegin; 137208449791SMatthew G. Knepley ierr = PetscFree(*fgeom);CHKERRQ(ierr); 137369291d52SBarry Smith ierr = DMRestoreWorkArray(dm, 0, MPIU_REAL, vol);CHKERRQ(ierr); 137408449791SMatthew G. Knepley PetscFunctionReturn(0); 137508449791SMatthew G. Knepley } 137608449791SMatthew G. Knepley 13774a3e9fdbSToby Isaac static PetscErrorCode ISIntersect_Caching(IS is1, IS is2, IS *isect) 137808449791SMatthew G. Knepley { 137908449791SMatthew G. Knepley PetscErrorCode ierr; 138008449791SMatthew G. Knepley 138108449791SMatthew G. Knepley PetscFunctionBegin; 13824a3e9fdbSToby Isaac *isect = NULL; 13834a3e9fdbSToby Isaac if (is2 && is1) { 13844a3e9fdbSToby Isaac char composeStr[33] = {0}; 13854a3e9fdbSToby Isaac PetscObjectId is2id; 13864a3e9fdbSToby Isaac 13874a3e9fdbSToby Isaac ierr = PetscObjectGetId((PetscObject)is2,&is2id);CHKERRQ(ierr); 13884a3e9fdbSToby Isaac ierr = PetscSNPrintf(composeStr,32,"ISIntersect_Caching_%x",is2id);CHKERRQ(ierr); 13894a3e9fdbSToby Isaac ierr = PetscObjectQuery((PetscObject) is1, composeStr, (PetscObject *) isect);CHKERRQ(ierr); 13904a3e9fdbSToby Isaac if (*isect == NULL) { 13914a3e9fdbSToby Isaac ierr = ISIntersect(is1, is2, isect);CHKERRQ(ierr); 13924a3e9fdbSToby Isaac ierr = PetscObjectCompose((PetscObject) is1, composeStr, (PetscObject) *isect);CHKERRQ(ierr); 13934a3e9fdbSToby Isaac } else { 13944a3e9fdbSToby Isaac ierr = PetscObjectReference((PetscObject) *isect);CHKERRQ(ierr); 13954a3e9fdbSToby Isaac } 13964a3e9fdbSToby Isaac } 13974a3e9fdbSToby Isaac PetscFunctionReturn(0); 13984a3e9fdbSToby Isaac } 13994a3e9fdbSToby Isaac 1400c330f8ffSToby Isaac static PetscErrorCode DMPlexComputeBdResidual_Single_Internal(DM dm, PetscReal t, DMLabel label, PetscInt numValues, const PetscInt values[], PetscInt field, Vec locX, Vec locX_t, Vec locF, DMField coordField, IS facetIS) 140108449791SMatthew G. Knepley { 140208449791SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1403023fee6eSMatthew G. Knepley DM plex = NULL, plexA = NULL; 140408449791SMatthew G. Knepley PetscDS prob, probAux = NULL; 140508449791SMatthew G. Knepley PetscSection section, sectionAux = NULL; 140608449791SMatthew G. Knepley Vec locA = NULL; 1407c330f8ffSToby Isaac PetscFEGeom *fgeom; 140808449791SMatthew G. Knepley PetscScalar *u = NULL, *u_t = NULL, *a = NULL, *elemVec = NULL; 140908449791SMatthew G. Knepley PetscInt v; 1410c330f8ffSToby Isaac PetscInt totDim, totDimAux = 0; 141108449791SMatthew G. Knepley PetscErrorCode ierr; 141208449791SMatthew G. Knepley 141308449791SMatthew G. Knepley PetscFunctionBegin; 1414023fee6eSMatthew G. Knepley ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 14154236e4b7SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 141608449791SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 14174d0b9603SSander Arens ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 14182d91c981SSander Arens ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &locA);CHKERRQ(ierr); 14192d91c981SSander Arens if (locA) { 14204236e4b7SMatthew G. Knepley DM dmAux; 14214236e4b7SMatthew G. Knepley 14222d91c981SSander Arens ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr); 1423023fee6eSMatthew G. Knepley ierr = DMConvert(dmAux, DMPLEX, &plexA);CHKERRQ(ierr); 1424023fee6eSMatthew G. Knepley ierr = DMGetDS(plexA, &probAux);CHKERRQ(ierr); 14254d0b9603SSander Arens ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 1426023fee6eSMatthew G. Knepley ierr = DMGetDefaultSection(plexA, §ionAux);CHKERRQ(ierr); 14272d91c981SSander Arens } 14284236e4b7SMatthew G. Knepley for (v = 0; v < numValues; ++v) { 1429c330f8ffSToby Isaac PetscBool isAffine; 1430c330f8ffSToby Isaac PetscQuadrature qGeom = NULL; 143124cdb843SMatthew G. Knepley IS pointIS; 143224cdb843SMatthew G. Knepley const PetscInt *points; 1433f74ed4f0SToby Isaac PetscInt numFaces, face, Nq; 143424cdb843SMatthew G. Knepley 1435a8e83e26SSanderA ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr); 143622734eb1Ssarens if (!pointIS) continue; /* No points with that id on this process */ 1437c330f8ffSToby Isaac { 1438c330f8ffSToby Isaac IS isectIS; 1439c330f8ffSToby Isaac 14404a3e9fdbSToby Isaac /* TODO: Special cases of ISIntersect where it is quick to check a priori if one is a superset of the other */ 14414a3e9fdbSToby Isaac ierr = ISIntersect_Caching(facetIS,pointIS,&isectIS);CHKERRQ(ierr); 1442c330f8ffSToby Isaac ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1443c330f8ffSToby Isaac pointIS = isectIS; 144424cdb843SMatthew G. Knepley } 1445c330f8ffSToby Isaac ierr = ISGetLocalSize(pointIS,&numFaces);CHKERRQ(ierr); 1446c330f8ffSToby Isaac ierr = ISGetIndices(pointIS,&points);CHKERRQ(ierr); 1447c330f8ffSToby Isaac ierr = PetscMalloc4(numFaces*totDim, &u, locX_t ? numFaces*totDim : 0, &u_t, numFaces*totDim, &elemVec, locA ? numFaces*totDimAux : 0, &a);CHKERRQ(ierr); 1448c330f8ffSToby Isaac ierr = DMFieldGetFEInvariance(coordField,pointIS,NULL,&isAffine,NULL);CHKERRQ(ierr); 1449c330f8ffSToby Isaac if (isAffine) { 1450c330f8ffSToby Isaac ierr = DMFieldCreateDefaultQuadrature(coordField,pointIS,&qGeom);CHKERRQ(ierr); 1451c330f8ffSToby Isaac } 1452c330f8ffSToby Isaac if (!qGeom) { 1453c330f8ffSToby Isaac PetscFE fe; 1454c330f8ffSToby Isaac 1455c330f8ffSToby Isaac ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 1456c330f8ffSToby Isaac ierr = PetscFEGetFaceQuadrature(fe, &qGeom);CHKERRQ(ierr); 1457c330f8ffSToby Isaac ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr); 1458c330f8ffSToby Isaac } 1459c330f8ffSToby Isaac ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 14604a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr); 1461c330f8ffSToby Isaac for (face = 0; face < numFaces; ++face) { 1462c330f8ffSToby Isaac const PetscInt point = points[face], *support, *cone; 146324cdb843SMatthew G. Knepley PetscScalar *x = NULL; 14649bfb2fe4SJed Brown PetscInt i, coneSize, faceLoc; 146524cdb843SMatthew G. Knepley 14664d0b9603SSander Arens ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 14674d0b9603SSander Arens ierr = DMPlexGetConeSize(dm, support[0], &coneSize);CHKERRQ(ierr); 14684d0b9603SSander Arens ierr = DMPlexGetCone(dm, support[0], &cone);CHKERRQ(ierr); 14694d0b9603SSander Arens for (faceLoc = 0; faceLoc < coneSize; ++faceLoc) if (cone[faceLoc] == point) break; 14704236e4b7SMatthew G. Knepley if (faceLoc == coneSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %D in cone of support[0] %D", point, support[0]); 1471c330f8ffSToby Isaac fgeom->face[face][0] = faceLoc; 14724d0b9603SSander Arens ierr = DMPlexVecGetClosure(dm, section, locX, support[0], NULL, &x);CHKERRQ(ierr); 14734d0b9603SSander Arens for (i = 0; i < totDim; ++i) u[face*totDim+i] = x[i]; 1474023fee6eSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plex, section, locX, support[0], NULL, &x);CHKERRQ(ierr); 147508449791SMatthew G. Knepley if (locX_t) { 1476023fee6eSMatthew G. Knepley ierr = DMPlexVecGetClosure(plex, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr); 14774d0b9603SSander Arens for (i = 0; i < totDim; ++i) u_t[face*totDim+i] = x[i]; 1478023fee6eSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plex, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr); 147924cdb843SMatthew G. Knepley } 14802d91c981SSander Arens if (locA) { 1481023fee6eSMatthew G. Knepley PetscInt subp; 1482023fee6eSMatthew G. Knepley ierr = DMPlexGetSubpoint(plexA, support[0], &subp);CHKERRQ(ierr); 1483023fee6eSMatthew G. Knepley ierr = DMPlexVecGetClosure(plexA, sectionAux, locA, subp, NULL, &x);CHKERRQ(ierr); 14844d0b9603SSander Arens for (i = 0; i < totDimAux; ++i) a[face*totDimAux+i] = x[i]; 1485023fee6eSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plexA, sectionAux, locA, subp, NULL, &x);CHKERRQ(ierr); 148624cdb843SMatthew G. Knepley } 148724cdb843SMatthew G. Knepley } 14884d0b9603SSander Arens ierr = PetscMemzero(elemVec, numFaces*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 1489cbf52bb1SSander Arens { 149024cdb843SMatthew G. Knepley PetscFE fe; 1491f74ed4f0SToby Isaac PetscInt Nb; 1492c330f8ffSToby Isaac PetscFEGeom *chunkGeom = NULL; 149324cdb843SMatthew G. Knepley /* Conforming batches */ 149424cdb843SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 149524cdb843SMatthew G. Knepley /* Remainder */ 149624cdb843SMatthew G. Knepley PetscInt Nr, offset; 149724cdb843SMatthew G. Knepley 14984d0b9603SSander Arens ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fe);CHKERRQ(ierr); 149924cdb843SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 150024cdb843SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 1501c330f8ffSToby Isaac /* TODO: documentation is unclear about what is going on with these numbers: how should Nb / Nq factor in ? */ 1502c330f8ffSToby Isaac blockSize = Nb; 150324cdb843SMatthew G. Knepley batchSize = numBlocks * blockSize; 150424cdb843SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 150524cdb843SMatthew G. Knepley numChunks = numFaces / (numBatches*batchSize); 150624cdb843SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 150724cdb843SMatthew G. Knepley Nr = numFaces % (numBatches*batchSize); 150824cdb843SMatthew G. Knepley offset = numFaces - Nr; 1509c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(fgeom,0,offset,&chunkGeom);CHKERRQ(ierr); 1510c330f8ffSToby Isaac ierr = PetscFEIntegrateBdResidual(fe, prob, field, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec);CHKERRQ(ierr); 1511c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr); 1512c330f8ffSToby Isaac ierr = PetscFEIntegrateBdResidual(fe, prob, field, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, a ? &a[offset*totDimAux] : NULL, t, &elemVec[offset*totDim]);CHKERRQ(ierr); 1513c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr); 151424cdb843SMatthew G. Knepley } 1515c330f8ffSToby Isaac for (face = 0; face < numFaces; ++face) { 1516c330f8ffSToby Isaac const PetscInt point = points[face], *support; 151724cdb843SMatthew G. Knepley 15184d0b9603SSander Arens if (mesh->printFEM > 1) {ierr = DMPrintCellVector(point, "BdResidual", totDim, &elemVec[face*totDim]);CHKERRQ(ierr);} 1519023fee6eSMatthew G. Knepley ierr = DMPlexGetSupport(plex, point, &support);CHKERRQ(ierr); 1520023fee6eSMatthew G. Knepley ierr = DMPlexVecSetClosure(plex, NULL, locF, support[0], &elemVec[face*totDim], ADD_ALL_VALUES);CHKERRQ(ierr); 152124cdb843SMatthew G. Knepley } 15224a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr); 1523c330f8ffSToby Isaac ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 152424cdb843SMatthew G. Knepley ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 152524cdb843SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1526c330f8ffSToby Isaac ierr = PetscFree4(u, u_t, elemVec, a);CHKERRQ(ierr); 152724cdb843SMatthew G. Knepley } 1528023fee6eSMatthew G. Knepley if (plex) {ierr = DMDestroy(&plex);CHKERRQ(ierr);} 1529023fee6eSMatthew G. Knepley if (plexA) {ierr = DMDestroy(&plexA);CHKERRQ(ierr);} 15304236e4b7SMatthew G. Knepley PetscFunctionReturn(0); 1531a8e83e26SSanderA } 15324236e4b7SMatthew G. Knepley 15334236e4b7SMatthew G. Knepley PetscErrorCode DMPlexComputeBdResidual_Internal(DM dm, Vec locX, Vec locX_t, PetscReal t, Vec locF, void *user) 15344236e4b7SMatthew G. Knepley { 15354236e4b7SMatthew G. Knepley PetscDS prob; 1536a179f353SToby Isaac PetscInt dim, numBd, bd; 1537a179f353SToby Isaac DMLabel depthLabel; 1538c330f8ffSToby Isaac DMField coordField = NULL; 1539c330f8ffSToby Isaac IS facetIS; 15404236e4b7SMatthew G. Knepley PetscErrorCode ierr; 15414236e4b7SMatthew G. Knepley 15424236e4b7SMatthew G. Knepley PetscFunctionBegin; 15434236e4b7SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 1544a179f353SToby Isaac ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 1545c330f8ffSToby Isaac ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1546a179f353SToby Isaac ierr = DMLabelGetStratumIS(depthLabel,dim - 1,&facetIS);CHKERRQ(ierr); 15474236e4b7SMatthew G. Knepley ierr = PetscDSGetNumBoundary(prob, &numBd);CHKERRQ(ierr); 15484a3e9fdbSToby Isaac ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 15494236e4b7SMatthew G. Knepley for (bd = 0; bd < numBd; ++bd) { 15504236e4b7SMatthew G. Knepley DMBoundaryConditionType type; 15514236e4b7SMatthew G. Knepley const char *bdLabel; 15524236e4b7SMatthew G. Knepley DMLabel label; 15534236e4b7SMatthew G. Knepley const PetscInt *values; 15544236e4b7SMatthew G. Knepley PetscInt field, numValues; 15554236e4b7SMatthew G. Knepley PetscObject obj; 15564236e4b7SMatthew G. Knepley PetscClassId id; 15574236e4b7SMatthew G. Knepley 15584236e4b7SMatthew G. Knepley ierr = PetscDSGetBoundary(prob, bd, &type, NULL, &bdLabel, &field, NULL, NULL, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 15594236e4b7SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 15604236e4b7SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 15614236e4b7SMatthew G. Knepley if ((id != PETSCFE_CLASSID) || (type & DM_BC_ESSENTIAL)) continue; 15624236e4b7SMatthew G. Knepley ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 1563c330f8ffSToby Isaac ierr = DMPlexComputeBdResidual_Single_Internal(dm, t, label, numValues, values, field, locX, locX_t, locF, coordField, facetIS);CHKERRQ(ierr); 15644236e4b7SMatthew G. Knepley } 1565c330f8ffSToby Isaac ierr = ISDestroy(&facetIS);CHKERRQ(ierr); 156608449791SMatthew G. Knepley PetscFunctionReturn(0); 156708449791SMatthew G. Knepley } 156808449791SMatthew G. Knepley 15694a3e9fdbSToby Isaac PetscErrorCode DMPlexComputeResidual_Internal(DM dm, IS cellIS, PetscReal time, Vec locX, Vec locX_t, PetscReal t, Vec locF, void *user) 157008449791SMatthew G. Knepley { 157108449791SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 157208449791SMatthew G. Knepley const char *name = "Residual"; 157308449791SMatthew G. Knepley DM dmAux = NULL; 157408449791SMatthew G. Knepley DM dmGrad = NULL; 157508449791SMatthew G. Knepley DMLabel ghostLabel = NULL; 157608449791SMatthew G. Knepley PetscDS prob = NULL; 157708449791SMatthew G. Knepley PetscDS probAux = NULL; 157808449791SMatthew G. Knepley PetscSection section = NULL; 157908449791SMatthew G. Knepley PetscBool useFEM = PETSC_FALSE; 158008449791SMatthew G. Knepley PetscBool useFVM = PETSC_FALSE; 1581b2666ceaSMatthew G. Knepley PetscBool isImplicit = (locX_t || time == PETSC_MIN_REAL) ? PETSC_TRUE : PETSC_FALSE; 158208449791SMatthew G. Knepley PetscFV fvm = NULL; 158308449791SMatthew G. Knepley PetscFVCellGeom *cgeomFVM = NULL; 158408449791SMatthew G. Knepley PetscFVFaceGeom *fgeomFVM = NULL; 1585c330f8ffSToby Isaac DMField coordField = NULL; 1586c330f8ffSToby Isaac Vec locA, cellGeometryFVM = NULL, faceGeometryFVM = NULL, grad, locGrad = NULL; 15873755293bSMatthew G. Knepley PetscScalar *u = NULL, *u_t, *a, *uL, *uR; 15889044fa66SMatthew G. Knepley IS chunkIS; 15899044fa66SMatthew G. Knepley const PetscInt *cells; 15909044fa66SMatthew G. Knepley PetscInt cStart, cEnd, numCells; 1591c4d4a4f8SMatthew G. Knepley PetscInt Nf, f, totDim, totDimAux, numChunks, cellChunkSize, faceChunkSize, chunk, fStart, fEnd; 15924a3e9fdbSToby Isaac PetscBool isAffine = PETSC_FALSE; 15934a3e9fdbSToby Isaac PetscQuadrature affineQuad = NULL, *quads = NULL; 15944a3e9fdbSToby Isaac PetscFEGeom *affineGeom = NULL, **geoms = NULL; 159508449791SMatthew G. Knepley PetscErrorCode ierr; 159608449791SMatthew G. Knepley 159708449791SMatthew G. Knepley PetscFunctionBegin; 159808449791SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr); 159908449791SMatthew G. Knepley /* TODO The places where we have to use isFE are probably the member functions for the PetscDisc class */ 1600195142f5SMatthew G. Knepley /* TODO The FVM geometry is over-manipulated. Make the precalc functions return exactly what we need */ 160108449791SMatthew G. Knepley /* FEM+FVM */ 160208449791SMatthew G. Knepley /* 1: Get sizes from dm and dmAux */ 160308449791SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1604c58f1c22SToby Isaac ierr = DMGetLabel(dm, "ghost", &ghostLabel);CHKERRQ(ierr); 160508449791SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 160608449791SMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 160708449791SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 160808449791SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &locA);CHKERRQ(ierr); 160908449791SMatthew G. Knepley if (locA) { 161008449791SMatthew G. Knepley ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr); 161108449791SMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 161208449791SMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 161308449791SMatthew G. Knepley } 161408449791SMatthew G. Knepley /* 2: Get geometric data */ 161508449791SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 161608449791SMatthew G. Knepley PetscObject obj; 161708449791SMatthew G. Knepley PetscClassId id; 16187173168dSMatthew G. Knepley PetscBool fimp; 161908449791SMatthew G. Knepley 16207173168dSMatthew G. Knepley ierr = PetscDSGetImplicit(prob, f, &fimp);CHKERRQ(ierr); 16217173168dSMatthew G. Knepley if (isImplicit != fimp) continue; 162208449791SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 162308449791SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 162408449791SMatthew G. Knepley if (id == PETSCFE_CLASSID) {useFEM = PETSC_TRUE;} 162508449791SMatthew G. Knepley if (id == PETSCFV_CLASSID) {useFVM = PETSC_TRUE; fvm = (PetscFV) obj;} 162608449791SMatthew G. Knepley } 162708449791SMatthew G. Knepley if (useFEM) { 16284a3e9fdbSToby Isaac ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 16294a3e9fdbSToby Isaac ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr); 16304a3e9fdbSToby Isaac if (isAffine) { 16314a3e9fdbSToby Isaac ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&affineQuad);CHKERRQ(ierr); 1632741db25dSToby Isaac if (affineQuad) { 16334a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,cellIS,affineQuad,PETSC_FALSE,&affineGeom);CHKERRQ(ierr); 1634741db25dSToby Isaac } 16354a3e9fdbSToby Isaac } else { 16364a3e9fdbSToby Isaac ierr = PetscCalloc2(Nf,&quads,Nf,&geoms);CHKERRQ(ierr); 16374a3e9fdbSToby Isaac for (f = 0; f < Nf; ++f) { 16384a3e9fdbSToby Isaac PetscObject obj; 16394a3e9fdbSToby Isaac PetscClassId id; 16404a3e9fdbSToby Isaac PetscBool fimp; 16412f84e9bcSToby Isaac 16424a3e9fdbSToby Isaac ierr = PetscDSGetImplicit(prob, f, &fimp);CHKERRQ(ierr); 16434a3e9fdbSToby Isaac if (isImplicit != fimp) continue; 16444a3e9fdbSToby Isaac ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 16454a3e9fdbSToby Isaac ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 16464a3e9fdbSToby Isaac if (id == PETSCFE_CLASSID) { 16474a3e9fdbSToby Isaac PetscFE fe = (PetscFE) obj; 16482f84e9bcSToby Isaac 16494a3e9fdbSToby Isaac ierr = PetscFEGetQuadrature(fe, &quads[f]);CHKERRQ(ierr); 16504a3e9fdbSToby Isaac ierr = PetscObjectReference((PetscObject)quads[f]);CHKERRQ(ierr); 16514a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,cellIS,quads[f],PETSC_FALSE,&geoms[f]);CHKERRQ(ierr); 16522f84e9bcSToby Isaac } 16532f84e9bcSToby Isaac } 16542f84e9bcSToby Isaac } 165508449791SMatthew G. Knepley } 165608449791SMatthew G. Knepley if (useFVM) { 165708449791SMatthew G. Knepley ierr = DMPlexSNESGetGeometryFVM(dm, &faceGeometryFVM, &cellGeometryFVM, NULL);CHKERRQ(ierr); 165808449791SMatthew G. Knepley ierr = VecGetArrayRead(faceGeometryFVM, (const PetscScalar **) &fgeomFVM);CHKERRQ(ierr); 165908449791SMatthew G. Knepley ierr = VecGetArrayRead(cellGeometryFVM, (const PetscScalar **) &cgeomFVM);CHKERRQ(ierr); 166008449791SMatthew G. Knepley /* Reconstruct and limit cell gradients */ 166108449791SMatthew G. Knepley ierr = DMPlexSNESGetGradientDM(dm, fvm, &dmGrad);CHKERRQ(ierr); 166208449791SMatthew G. Knepley if (dmGrad) { 166308449791SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 166408449791SMatthew G. Knepley ierr = DMGetGlobalVector(dmGrad, &grad);CHKERRQ(ierr); 1665de555695SMatthew G. Knepley ierr = DMPlexReconstructGradients_Internal(dm, fvm, fStart, fEnd, faceGeometryFVM, cellGeometryFVM, locX, grad);CHKERRQ(ierr); 166608449791SMatthew G. Knepley /* Communicate gradient values */ 166708449791SMatthew G. Knepley ierr = DMGetLocalVector(dmGrad, &locGrad);CHKERRQ(ierr); 166808449791SMatthew G. Knepley ierr = DMGlobalToLocalBegin(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); 166908449791SMatthew G. Knepley ierr = DMGlobalToLocalEnd(dmGrad, grad, INSERT_VALUES, locGrad);CHKERRQ(ierr); 167008449791SMatthew G. Knepley ierr = DMRestoreGlobalVector(dmGrad, &grad);CHKERRQ(ierr); 167108449791SMatthew G. Knepley } 1672bdd6f66aSToby Isaac /* Handle non-essential (e.g. outflow) boundary values */ 1673bdd6f66aSToby Isaac ierr = DMPlexInsertBoundaryValues(dm, PETSC_FALSE, locX, time, faceGeometryFVM, cellGeometryFVM, locGrad);CHKERRQ(ierr); 167408449791SMatthew G. Knepley } 167508449791SMatthew G. Knepley /* Loop over chunks */ 16769044fa66SMatthew G. Knepley ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 167708449791SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 16789044fa66SMatthew G. Knepley if (useFEM) {ierr = ISCreate(PETSC_COMM_SELF, &chunkIS);CHKERRQ(ierr);} 16799044fa66SMatthew G. Knepley numCells = cEnd - cStart; 168008449791SMatthew G. Knepley numChunks = 1; 16814a3e9fdbSToby Isaac cellChunkSize = numCells/numChunks; 168208449791SMatthew G. Knepley faceChunkSize = (fEnd - fStart)/numChunks; 1683741db25dSToby Isaac numChunks = PetscMin(1,numCells); 168408449791SMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk) { 16852eefff9cSMatthew G. Knepley PetscScalar *elemVec, *fluxL, *fluxR; 16862eefff9cSMatthew G. Knepley PetscReal *vol; 168708449791SMatthew G. Knepley PetscFVFaceGeom *fgeom; 16889044fa66SMatthew G. Knepley PetscInt cS = cStart+chunk*cellChunkSize, cE = PetscMin(cS+cellChunkSize, cEnd), numCells = cE - cS, c; 16893755293bSMatthew G. Knepley PetscInt fS = fStart+chunk*faceChunkSize, fE = PetscMin(fS+faceChunkSize, fEnd), numFaces = 0, face; 169008449791SMatthew G. Knepley 169108449791SMatthew G. Knepley /* Extract field coefficients */ 169208449791SMatthew G. Knepley if (useFEM) { 16939044fa66SMatthew G. Knepley ierr = ISGetPointSubrange(chunkIS, cS, cE, cells);CHKERRQ(ierr); 16949044fa66SMatthew G. Knepley ierr = DMPlexGetCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a);CHKERRQ(ierr); 169569291d52SBarry Smith ierr = DMGetWorkArray(dm, numCells*totDim, MPIU_SCALAR, &elemVec);CHKERRQ(ierr); 1696215c4595SMatthew G. Knepley ierr = PetscMemzero(elemVec, numCells*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 169708449791SMatthew G. Knepley } 169808449791SMatthew G. Knepley if (useFVM) { 16995f942ad5SMatthew G. Knepley ierr = DMPlexGetFaceFields(dm, fS, fE, locX, locX_t, faceGeometryFVM, cellGeometryFVM, locGrad, &numFaces, &uL, &uR);CHKERRQ(ierr); 17005f942ad5SMatthew G. Knepley ierr = DMPlexGetFaceGeometry(dm, fS, fE, faceGeometryFVM, cellGeometryFVM, &numFaces, &fgeom, &vol);CHKERRQ(ierr); 170169291d52SBarry Smith ierr = DMGetWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxL);CHKERRQ(ierr); 170269291d52SBarry Smith ierr = DMGetWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxR);CHKERRQ(ierr); 1703215c4595SMatthew G. Knepley ierr = PetscMemzero(fluxL, numFaces*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 1704215c4595SMatthew G. Knepley ierr = PetscMemzero(fluxR, numFaces*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 170508449791SMatthew G. Knepley } 170608449791SMatthew G. Knepley /* TODO We will interlace both our field coefficients (u, u_t, uL, uR, etc.) and our output (elemVec, fL, fR). I think this works */ 170708449791SMatthew G. Knepley /* Loop over fields */ 170808449791SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 170908449791SMatthew G. Knepley PetscObject obj; 171008449791SMatthew G. Knepley PetscClassId id; 17117173168dSMatthew G. Knepley PetscBool fimp; 171208449791SMatthew G. Knepley PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset; 171308449791SMatthew G. Knepley 17147173168dSMatthew G. Knepley ierr = PetscDSGetImplicit(prob, f, &fimp);CHKERRQ(ierr); 17157173168dSMatthew G. Knepley if (isImplicit != fimp) continue; 171608449791SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 171708449791SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 171808449791SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 171908449791SMatthew G. Knepley PetscFE fe = (PetscFE) obj; 17204a3e9fdbSToby Isaac PetscFEGeom *geom = affineGeom ? affineGeom : geoms[f]; 17214a3e9fdbSToby Isaac PetscFEGeom *chunkGeom = NULL; 17224a3e9fdbSToby Isaac PetscQuadrature quad = affineQuad ? affineQuad : quads[f]; 172308449791SMatthew G. Knepley PetscInt Nq, Nb; 172408449791SMatthew G. Knepley 172508449791SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 17264a3e9fdbSToby Isaac ierr = PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 172708449791SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 1728c330f8ffSToby Isaac blockSize = Nb; 172908449791SMatthew G. Knepley batchSize = numBlocks * blockSize; 173008449791SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 173108449791SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 173208449791SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 173308449791SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 173408449791SMatthew G. Knepley offset = numCells - Nr; 173508449791SMatthew G. Knepley /* Integrate FE residual to get elemVec (need fields at quadrature points) */ 173608449791SMatthew G. Knepley /* For FV, I think we use a P0 basis and the cell coefficients (for subdivided cells, we can tweak the basis tabulation to be the indicator function) */ 17374a3e9fdbSToby Isaac ierr = PetscFEGeomGetChunk(geom,0,offset,&chunkGeom);CHKERRQ(ierr); 1738c330f8ffSToby Isaac ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec);CHKERRQ(ierr); 17394a3e9fdbSToby Isaac ierr = PetscFEGeomGetChunk(geom,offset,numCells,&chunkGeom);CHKERRQ(ierr); 1740c330f8ffSToby Isaac ierr = PetscFEIntegrateResidual(fe, prob, f, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, &elemVec[offset*totDim]);CHKERRQ(ierr); 17414a3e9fdbSToby Isaac ierr = PetscFEGeomRestoreChunk(geom,offset,numCells,&chunkGeom);CHKERRQ(ierr); 174208449791SMatthew G. Knepley } else if (id == PETSCFV_CLASSID) { 174308449791SMatthew G. Knepley PetscFV fv = (PetscFV) obj; 174408449791SMatthew G. Knepley 174508449791SMatthew G. Knepley Ne = numFaces; 174608449791SMatthew G. Knepley /* Riemann solve over faces (need fields at face centroids) */ 174708449791SMatthew G. Knepley /* We need to evaluate FE fields at those coordinates */ 174808449791SMatthew G. Knepley ierr = PetscFVIntegrateRHSFunction(fv, prob, f, Ne, fgeom, vol, uL, uR, fluxL, fluxR);CHKERRQ(ierr); 174908449791SMatthew G. Knepley } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 175008449791SMatthew G. Knepley } 175108449791SMatthew G. Knepley /* Loop over domain */ 175208449791SMatthew G. Knepley if (useFEM) { 175308449791SMatthew G. Knepley /* Add elemVec to locX */ 17549044fa66SMatthew G. Knepley for (c = cS; c < cE; ++c) { 17559044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 17569044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 1757f905620eSMatthew G. Knepley 17589044fa66SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellVector(cell, name, totDim, &elemVec[cind*totDim]);CHKERRQ(ierr);} 1759b4920ed3SToby Isaac if (ghostLabel) { 1760b4920ed3SToby Isaac PetscInt ghostVal; 1761b4920ed3SToby Isaac 1762b4920ed3SToby Isaac ierr = DMLabelGetValue(ghostLabel,cell,&ghostVal);CHKERRQ(ierr); 1763b4920ed3SToby Isaac if (ghostVal > 0) continue; 1764b4920ed3SToby Isaac } 17659044fa66SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, locF, cell, &elemVec[cind*totDim], ADD_ALL_VALUES);CHKERRQ(ierr); 176608449791SMatthew G. Knepley } 176708449791SMatthew G. Knepley } 176808449791SMatthew G. Knepley if (useFVM) { 17694a394323SMatthew G. Knepley PetscScalar *fa; 177008449791SMatthew G. Knepley PetscInt iface; 177108449791SMatthew G. Knepley 177208449791SMatthew G. Knepley ierr = VecGetArray(locF, &fa);CHKERRQ(ierr); 1773c10b5f1bSMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1774c10b5f1bSMatthew G. Knepley PetscFV fv; 1775c10b5f1bSMatthew G. Knepley PetscObject obj; 1776c10b5f1bSMatthew G. Knepley PetscClassId id; 17774a394323SMatthew G. Knepley PetscInt foff, pdim; 1778c10b5f1bSMatthew G. Knepley 1779c10b5f1bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1780c10b5f1bSMatthew G. Knepley ierr = PetscDSGetFieldOffset(prob, f, &foff);CHKERRQ(ierr); 1781c10b5f1bSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1782c10b5f1bSMatthew G. Knepley if (id != PETSCFV_CLASSID) continue; 1783c10b5f1bSMatthew G. Knepley fv = (PetscFV) obj; 1784c10b5f1bSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr); 1785c10b5f1bSMatthew G. Knepley /* Accumulate fluxes to cells */ 178608449791SMatthew G. Knepley for (face = fS, iface = 0; face < fE; ++face) { 17879044fa66SMatthew G. Knepley const PetscInt *scells; 1788b4920ed3SToby Isaac PetscScalar *fL = NULL, *fR = NULL; 17897c45b140SToby Isaac PetscInt ghost, d, nsupp, nchild; 179008449791SMatthew G. Knepley 179108449791SMatthew G. Knepley ierr = DMLabelGetValue(ghostLabel, face, &ghost);CHKERRQ(ierr); 1792ffe9ad51SToby Isaac ierr = DMPlexGetSupportSize(dm, face, &nsupp);CHKERRQ(ierr); 17937c45b140SToby Isaac ierr = DMPlexGetTreeChildren(dm, face, &nchild, NULL);CHKERRQ(ierr); 17947c45b140SToby Isaac if (ghost >= 0 || nsupp > 2 || nchild > 0) continue; 17959044fa66SMatthew G. Knepley ierr = DMPlexGetSupport(dm, face, &scells);CHKERRQ(ierr); 17969044fa66SMatthew G. Knepley ierr = DMLabelGetValue(ghostLabel,scells[0],&ghost);CHKERRQ(ierr); 17979044fa66SMatthew G. Knepley if (ghost <= 0) {ierr = DMPlexPointLocalFieldRef(dm, scells[0], f, fa, &fL);CHKERRQ(ierr);} 17989044fa66SMatthew G. Knepley ierr = DMLabelGetValue(ghostLabel,scells[1],&ghost);CHKERRQ(ierr); 17999044fa66SMatthew G. Knepley if (ghost <= 0) {ierr = DMPlexPointLocalFieldRef(dm, scells[1], f, fa, &fR);CHKERRQ(ierr);} 1800c10b5f1bSMatthew G. Knepley for (d = 0; d < pdim; ++d) { 1801c10b5f1bSMatthew G. Knepley if (fL) fL[d] -= fluxL[iface*totDim+foff+d]; 1802c10b5f1bSMatthew G. Knepley if (fR) fR[d] += fluxR[iface*totDim+foff+d]; 180308449791SMatthew G. Knepley } 180408449791SMatthew G. Knepley ++iface; 180508449791SMatthew G. Knepley } 1806dab51205SMatthew G. Knepley } 1807dab51205SMatthew G. Knepley ierr = VecRestoreArray(locF, &fa);CHKERRQ(ierr); 1808dab51205SMatthew G. Knepley } 1809c10b5f1bSMatthew G. Knepley /* Handle time derivative */ 1810c10b5f1bSMatthew G. Knepley if (locX_t) { 1811dab51205SMatthew G. Knepley PetscScalar *x_t, *fa; 1812dab51205SMatthew G. Knepley 1813dab51205SMatthew G. Knepley ierr = VecGetArray(locF, &fa);CHKERRQ(ierr); 1814c10b5f1bSMatthew G. Knepley ierr = VecGetArray(locX_t, &x_t);CHKERRQ(ierr); 1815dab51205SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1816dab51205SMatthew G. Knepley PetscFV fv; 1817dab51205SMatthew G. Knepley PetscObject obj; 1818dab51205SMatthew G. Knepley PetscClassId id; 1819dab51205SMatthew G. Knepley PetscInt pdim, d; 1820dab51205SMatthew G. Knepley 1821dab51205SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1822dab51205SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1823dab51205SMatthew G. Knepley if (id != PETSCFV_CLASSID) continue; 1824dab51205SMatthew G. Knepley fv = (PetscFV) obj; 1825dab51205SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr); 18269044fa66SMatthew G. Knepley for (c = cS; c < cE; ++c) { 18279044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 1828c10b5f1bSMatthew G. Knepley PetscScalar *u_t, *r; 1829c10b5f1bSMatthew G. Knepley 1830b4920ed3SToby Isaac if (ghostLabel) { 1831b4920ed3SToby Isaac PetscInt ghostVal; 1832b4920ed3SToby Isaac 1833b4920ed3SToby Isaac ierr = DMLabelGetValue(ghostLabel, cell, &ghostVal);CHKERRQ(ierr); 1834b4920ed3SToby Isaac if (ghostVal > 0) continue; 1835b4920ed3SToby Isaac } 1836c10b5f1bSMatthew G. Knepley ierr = DMPlexPointLocalFieldRead(dm, cell, f, x_t, &u_t);CHKERRQ(ierr); 1837c10b5f1bSMatthew G. Knepley ierr = DMPlexPointLocalFieldRef(dm, cell, f, fa, &r);CHKERRQ(ierr); 1838d63b37e5SMatthew G. Knepley for (d = 0; d < pdim; ++d) r[d] += u_t[d]; 1839c10b5f1bSMatthew G. Knepley } 1840dab51205SMatthew G. Knepley } 1841c10b5f1bSMatthew G. Knepley ierr = VecRestoreArray(locX_t, &x_t);CHKERRQ(ierr); 184208449791SMatthew G. Knepley ierr = VecRestoreArray(locF, &fa);CHKERRQ(ierr); 184308449791SMatthew G. Knepley } 184408449791SMatthew G. Knepley if (useFEM) { 18459044fa66SMatthew G. Knepley ierr = DMPlexRestoreCellFields(dm, chunkIS, locX, locX_t, locA, &u, &u_t, &a);CHKERRQ(ierr); 184669291d52SBarry Smith ierr = DMRestoreWorkArray(dm, numCells*totDim, MPIU_SCALAR, &elemVec);CHKERRQ(ierr); 184708449791SMatthew G. Knepley } 184808449791SMatthew G. Knepley if (useFVM) { 18495f942ad5SMatthew G. Knepley ierr = DMPlexRestoreFaceFields(dm, fS, fE, locX, locX_t, faceGeometryFVM, cellGeometryFVM, locGrad, &numFaces, &uL, &uR);CHKERRQ(ierr); 18505f942ad5SMatthew G. Knepley ierr = DMPlexRestoreFaceGeometry(dm, fS, fE, faceGeometryFVM, cellGeometryFVM, &numFaces, &fgeom, &vol);CHKERRQ(ierr); 185169291d52SBarry Smith ierr = DMRestoreWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxL);CHKERRQ(ierr); 185269291d52SBarry Smith ierr = DMRestoreWorkArray(dm, numFaces*totDim, MPIU_SCALAR, &fluxR);CHKERRQ(ierr); 185308449791SMatthew G. Knepley if (dmGrad) {ierr = DMRestoreLocalVector(dmGrad, &locGrad);CHKERRQ(ierr);} 185408449791SMatthew G. Knepley } 185508449791SMatthew G. Knepley } 185603fee3f0SMatthew G. Knepley if (useFEM) {ierr = ISDestroy(&chunkIS);CHKERRQ(ierr);} 18579044fa66SMatthew G. Knepley ierr = ISRestorePointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 185808449791SMatthew G. Knepley 18594a3e9fdbSToby Isaac if (useFEM) { 18604a3e9fdbSToby Isaac ierr = DMPlexComputeBdResidual_Internal(dm, locX, locX_t, t, locF, user);CHKERRQ(ierr); 18614a3e9fdbSToby Isaac 18624a3e9fdbSToby Isaac if (isAffine) { 18634a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,cellIS,affineQuad,PETSC_FALSE,&affineGeom);CHKERRQ(ierr); 18644a3e9fdbSToby Isaac ierr = PetscQuadratureDestroy(&affineQuad);CHKERRQ(ierr); 18654a3e9fdbSToby Isaac } else { 18664a3e9fdbSToby Isaac for (f = 0; f < Nf; ++f) { 18674a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,cellIS,quads[f],PETSC_FALSE,&geoms[f]);CHKERRQ(ierr); 18684a3e9fdbSToby Isaac ierr = PetscQuadratureDestroy(&quads[f]);CHKERRQ(ierr); 18694a3e9fdbSToby Isaac } 18704a3e9fdbSToby Isaac ierr = PetscFree2(quads,geoms);CHKERRQ(ierr); 18714a3e9fdbSToby Isaac } 18724a3e9fdbSToby Isaac } 187308449791SMatthew G. Knepley 187408449791SMatthew G. Knepley /* FEM */ 187508449791SMatthew G. Knepley /* 1: Get sizes from dm and dmAux */ 187608449791SMatthew G. Knepley /* 2: Get geometric data */ 187708449791SMatthew G. Knepley /* 3: Handle boundary values */ 187808449791SMatthew G. Knepley /* 4: Loop over domain */ 187908449791SMatthew G. Knepley /* Extract coefficients */ 188008449791SMatthew G. Knepley /* Loop over fields */ 188108449791SMatthew G. Knepley /* Set tiling for FE*/ 188208449791SMatthew G. Knepley /* Integrate FE residual to get elemVec */ 188308449791SMatthew G. Knepley /* Loop over subdomain */ 188408449791SMatthew G. Knepley /* Loop over quad points */ 188508449791SMatthew G. Knepley /* Transform coords to real space */ 188608449791SMatthew G. Knepley /* Evaluate field and aux fields at point */ 188708449791SMatthew G. Knepley /* Evaluate residual at point */ 188808449791SMatthew G. Knepley /* Transform residual to real space */ 188908449791SMatthew G. Knepley /* Add residual to elemVec */ 189008449791SMatthew G. Knepley /* Loop over domain */ 189108449791SMatthew G. Knepley /* Add elemVec to locX */ 189208449791SMatthew G. Knepley 189308449791SMatthew G. Knepley /* FVM */ 189408449791SMatthew G. Knepley /* Get geometric data */ 189508449791SMatthew G. Knepley /* If using gradients */ 189608449791SMatthew G. Knepley /* Compute gradient data */ 189708449791SMatthew G. Knepley /* Loop over domain faces */ 189808449791SMatthew G. Knepley /* Count computational faces */ 189908449791SMatthew G. Knepley /* Reconstruct cell gradient */ 190008449791SMatthew G. Knepley /* Loop over domain cells */ 190108449791SMatthew G. Knepley /* Limit cell gradients */ 190208449791SMatthew G. Knepley /* Handle boundary values */ 190308449791SMatthew G. Knepley /* Loop over domain faces */ 190408449791SMatthew G. Knepley /* Read out field, centroid, normal, volume for each side of face */ 190508449791SMatthew G. Knepley /* Riemann solve over faces */ 190608449791SMatthew G. Knepley /* Loop over domain faces */ 190708449791SMatthew G. Knepley /* Accumulate fluxes to cells */ 190808449791SMatthew G. Knepley /* TODO Change printFEM to printDisc here */ 1909247ba720SToby Isaac if (mesh->printFEM) { 1910247ba720SToby Isaac Vec locFbc; 1911247ba720SToby Isaac PetscInt pStart, pEnd, p, maxDof; 1912247ba720SToby Isaac PetscScalar *zeroes; 1913247ba720SToby Isaac 1914247ba720SToby Isaac ierr = VecDuplicate(locF,&locFbc);CHKERRQ(ierr); 1915247ba720SToby Isaac ierr = VecCopy(locF,locFbc);CHKERRQ(ierr); 1916247ba720SToby Isaac ierr = PetscSectionGetChart(section,&pStart,&pEnd);CHKERRQ(ierr); 1917247ba720SToby Isaac ierr = PetscSectionGetMaxDof(section,&maxDof);CHKERRQ(ierr); 1918247ba720SToby Isaac ierr = PetscCalloc1(maxDof,&zeroes);CHKERRQ(ierr); 1919247ba720SToby Isaac for (p = pStart; p < pEnd; p++) { 1920247ba720SToby Isaac ierr = VecSetValuesSection(locFbc,section,p,zeroes,INSERT_BC_VALUES);CHKERRQ(ierr); 1921247ba720SToby Isaac } 1922247ba720SToby Isaac ierr = PetscFree(zeroes);CHKERRQ(ierr); 1923247ba720SToby Isaac ierr = DMPrintLocalVec(dm, name, mesh->printTol, locFbc);CHKERRQ(ierr); 1924247ba720SToby Isaac ierr = VecDestroy(&locFbc);CHKERRQ(ierr); 1925247ba720SToby Isaac } 192624cdb843SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_ResidualFEM,dm,0,0,0);CHKERRQ(ierr); 192724cdb843SMatthew G. Knepley PetscFunctionReturn(0); 192824cdb843SMatthew G. Knepley } 192924cdb843SMatthew G. Knepley 193011dd639bSMatthew G. Knepley static PetscErrorCode DMPlexComputeResidualFEM_Check_Internal(DM dm, Vec X, Vec X_t, PetscReal t, Vec F, void *user) 193124cdb843SMatthew G. Knepley { 193224cdb843SMatthew G. Knepley DM dmCh, dmAux; 1933c330f8ffSToby Isaac Vec A; 1934c330f8ffSToby Isaac DMField coordField = NULL; 193524cdb843SMatthew G. Knepley PetscDS prob, probCh, probAux = NULL; 193624cdb843SMatthew G. Knepley PetscSection section, sectionAux; 193724cdb843SMatthew G. Knepley PetscScalar *elemVec, *elemVecCh, *u, *u_t, *a = NULL; 1938c330f8ffSToby Isaac PetscInt Nf, f, numCells, cStart, cEnd, c; 19393755293bSMatthew G. Knepley PetscInt totDim, totDimAux = 0, diffCell = 0; 19404a3e9fdbSToby Isaac PetscInt depth; 1941c330f8ffSToby Isaac PetscBool isAffine; 1942c330f8ffSToby Isaac IS cellIS; 19434a3e9fdbSToby Isaac DMLabel depthLabel; 194424cdb843SMatthew G. Knepley PetscErrorCode ierr; 194524cdb843SMatthew G. Knepley 194624cdb843SMatthew G. Knepley PetscFunctionBegin; 194724cdb843SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 194824cdb843SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 194924cdb843SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 195024cdb843SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 195124cdb843SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 195224cdb843SMatthew G. Knepley numCells = cEnd - cStart; 195324cdb843SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmCh", (PetscObject *) &dmCh);CHKERRQ(ierr); 195424cdb843SMatthew G. Knepley ierr = DMGetDS(dmCh, &probCh);CHKERRQ(ierr); 195524cdb843SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 195624cdb843SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 195724cdb843SMatthew G. Knepley if (dmAux) { 195824cdb843SMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 195924cdb843SMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 196024cdb843SMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 196124cdb843SMatthew G. Knepley } 196224cdb843SMatthew G. Knepley ierr = VecSet(F, 0.0);CHKERRQ(ierr); 1963bbce034cSMatthew G. Knepley ierr = PetscMalloc3(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*totDim,&elemVec);CHKERRQ(ierr); 196424cdb843SMatthew G. Knepley ierr = PetscMalloc1(numCells*totDim,&elemVecCh);CHKERRQ(ierr); 196524cdb843SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 19664a3e9fdbSToby Isaac ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 19674a3e9fdbSToby Isaac ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 19684a3e9fdbSToby Isaac ierr = DMLabelGetStratumIS(depthLabel,depth,&cellIS);CHKERRQ(ierr); 19694a3e9fdbSToby Isaac ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 197024cdb843SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 197124cdb843SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 197224cdb843SMatthew G. Knepley PetscInt i; 197324cdb843SMatthew G. Knepley 197424cdb843SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 197524cdb843SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 197624cdb843SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, c, NULL, &x);CHKERRQ(ierr); 197724cdb843SMatthew G. Knepley if (X_t) { 197824cdb843SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 197924cdb843SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 198024cdb843SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, c, NULL, &x_t);CHKERRQ(ierr); 198124cdb843SMatthew G. Knepley } 198224cdb843SMatthew G. Knepley if (dmAux) { 19836da023fcSToby Isaac DM dmAuxPlex; 19846da023fcSToby Isaac 19856da023fcSToby Isaac ierr = DMSNESConvertPlex(dmAux,&dmAuxPlex, PETSC_FALSE);CHKERRQ(ierr); 19866da023fcSToby Isaac ierr = DMPlexVecGetClosure(dmAuxPlex, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 198724cdb843SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 19886da023fcSToby Isaac ierr = DMPlexVecRestoreClosure(dmAuxPlex, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 19896da023fcSToby Isaac ierr = DMDestroy(&dmAuxPlex);CHKERRQ(ierr); 199024cdb843SMatthew G. Knepley } 199124cdb843SMatthew G. Knepley } 199224cdb843SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 199324cdb843SMatthew G. Knepley PetscFE fe, feCh; 1994c330f8ffSToby Isaac PetscInt Nq, Nb; 199524cdb843SMatthew G. Knepley /* Conforming batches */ 199624cdb843SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 199724cdb843SMatthew G. Knepley /* Remainder */ 199824cdb843SMatthew G. Knepley PetscInt Nr, offset; 1999c330f8ffSToby Isaac PetscQuadrature qGeom = NULL; 2000c330f8ffSToby Isaac PetscFEGeom *cgeomFEM, *chunkGeom = NULL; 200124cdb843SMatthew G. Knepley 200224cdb843SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 200324cdb843SMatthew G. Knepley ierr = PetscDSGetDiscretization(probCh, f, (PetscObject *) &feCh);CHKERRQ(ierr); 200424cdb843SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 200524cdb843SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 2006c330f8ffSToby Isaac ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr); 2007c330f8ffSToby Isaac if (isAffine) { 2008c330f8ffSToby Isaac ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr); 2009c330f8ffSToby Isaac } 2010c330f8ffSToby Isaac if (!qGeom) { 2011c330f8ffSToby Isaac ierr = PetscFEGetQuadrature(fe, &qGeom);CHKERRQ(ierr); 2012c330f8ffSToby Isaac ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr); 2013c330f8ffSToby Isaac } 2014c330f8ffSToby Isaac ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 20154a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 2016c330f8ffSToby Isaac blockSize = Nb; 201724cdb843SMatthew G. Knepley batchSize = numBlocks * blockSize; 201824cdb843SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 201924cdb843SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 202024cdb843SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 202124cdb843SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 202224cdb843SMatthew G. Knepley offset = numCells - Nr; 2023c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 2024c330f8ffSToby Isaac ierr = PetscFEIntegrateResidual(fe, prob, f, Ne, chunkGeom, u, u_t, probAux, a, t, elemVec);CHKERRQ(ierr); 2025c330f8ffSToby Isaac ierr = PetscFEIntegrateResidual(feCh, prob, f, Ne, chunkGeom, u, u_t, probAux, a, t, elemVecCh);CHKERRQ(ierr); 2026c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&chunkGeom);CHKERRQ(ierr); 2027c330f8ffSToby Isaac ierr = PetscFEIntegrateResidual(fe, prob, f, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, &elemVec[offset*totDim]);CHKERRQ(ierr); 2028c330f8ffSToby Isaac ierr = PetscFEIntegrateResidual(feCh, prob, f, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, &elemVecCh[offset*totDim]);CHKERRQ(ierr); 2029c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&chunkGeom);CHKERRQ(ierr); 20304a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 2031c330f8ffSToby Isaac ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 203224cdb843SMatthew G. Knepley } 2033c330f8ffSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 203424cdb843SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 203524cdb843SMatthew G. Knepley PetscBool diff = PETSC_FALSE; 203624cdb843SMatthew G. Knepley PetscInt d; 203724cdb843SMatthew G. Knepley 203824cdb843SMatthew G. Knepley for (d = 0; d < totDim; ++d) if (PetscAbsScalar(elemVec[c*totDim+d] - elemVecCh[c*totDim+d]) > 1.0e-7) {diff = PETSC_TRUE;break;} 203924cdb843SMatthew G. Knepley if (diff) { 204024cdb843SMatthew G. Knepley ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Different cell %d\n", c);CHKERRQ(ierr); 204124cdb843SMatthew G. Knepley ierr = DMPrintCellVector(c, "Residual", totDim, &elemVec[c*totDim]);CHKERRQ(ierr); 204224cdb843SMatthew G. Knepley ierr = DMPrintCellVector(c, "Check Residual", totDim, &elemVecCh[c*totDim]);CHKERRQ(ierr); 204324cdb843SMatthew G. Knepley ++diffCell; 204424cdb843SMatthew G. Knepley } 204524cdb843SMatthew G. Knepley if (diffCell > 9) break; 2046c14a31d2SToby Isaac ierr = DMPlexVecSetClosure(dm, section, F, c, &elemVec[c*totDim], ADD_ALL_VALUES);CHKERRQ(ierr); 204724cdb843SMatthew G. Knepley } 2048bbce034cSMatthew G. Knepley ierr = PetscFree3(u,u_t,elemVec);CHKERRQ(ierr); 204924cdb843SMatthew G. Knepley ierr = PetscFree(elemVecCh);CHKERRQ(ierr); 205024cdb843SMatthew G. Knepley if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 205124cdb843SMatthew G. Knepley PetscFunctionReturn(0); 205224cdb843SMatthew G. Knepley } 205324cdb843SMatthew G. Knepley 205424cdb843SMatthew G. Knepley /*@ 205524cdb843SMatthew G. Knepley DMPlexSNESComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 205624cdb843SMatthew G. Knepley 205724cdb843SMatthew G. Knepley Input Parameters: 205824cdb843SMatthew G. Knepley + dm - The mesh 205924cdb843SMatthew G. Knepley . X - Local solution 206024cdb843SMatthew G. Knepley - user - The user context 206124cdb843SMatthew G. Knepley 206224cdb843SMatthew G. Knepley Output Parameter: 206324cdb843SMatthew G. Knepley . F - Local output vector 206424cdb843SMatthew G. Knepley 206524cdb843SMatthew G. Knepley Level: developer 206624cdb843SMatthew G. Knepley 206724cdb843SMatthew G. Knepley .seealso: DMPlexComputeJacobianActionFEM() 206824cdb843SMatthew G. Knepley @*/ 206924cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 207024cdb843SMatthew G. Knepley { 207124cdb843SMatthew G. Knepley PetscObject check; 20726da023fcSToby Isaac DM plex; 20734a3e9fdbSToby Isaac IS cellIS; 20744a3e9fdbSToby Isaac PetscInt depth; 207524cdb843SMatthew G. Knepley PetscErrorCode ierr; 207624cdb843SMatthew G. Knepley 207724cdb843SMatthew G. Knepley PetscFunctionBegin; 20786da023fcSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 20794a3e9fdbSToby Isaac ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 2080aeadca18SToby Isaac ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr); 20814a3e9fdbSToby Isaac if (!cellIS) { 20824a3e9fdbSToby Isaac ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr); 20834a3e9fdbSToby Isaac } 208424cdb843SMatthew G. Knepley /* The dmCh is used to check two mathematically equivalent discretizations for computational equivalence */ 20856da023fcSToby Isaac ierr = PetscObjectQuery((PetscObject) plex, "dmCh", &check);CHKERRQ(ierr); 208611dd639bSMatthew G. Knepley if (check) {ierr = DMPlexComputeResidualFEM_Check_Internal(plex, X, NULL, 0.0, F, user);CHKERRQ(ierr);} 20874a3e9fdbSToby Isaac else {ierr = DMPlexComputeResidual_Internal(plex, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr);} 20884a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 20899a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 209024cdb843SMatthew G. Knepley PetscFunctionReturn(0); 209124cdb843SMatthew G. Knepley } 209224cdb843SMatthew G. Knepley 2093bdd6f66aSToby Isaac /*@ 2094bdd6f66aSToby Isaac DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X 2095bdd6f66aSToby Isaac 2096bdd6f66aSToby Isaac Input Parameters: 2097bdd6f66aSToby Isaac + dm - The mesh 2098bdd6f66aSToby Isaac - user - The user context 2099bdd6f66aSToby Isaac 2100bdd6f66aSToby Isaac Output Parameter: 2101bdd6f66aSToby Isaac . X - Local solution 2102bdd6f66aSToby Isaac 2103bdd6f66aSToby Isaac Level: developer 2104bdd6f66aSToby Isaac 2105bdd6f66aSToby Isaac .seealso: DMPlexComputeJacobianActionFEM() 2106bdd6f66aSToby Isaac @*/ 2107bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user) 2108bdd6f66aSToby Isaac { 2109bdd6f66aSToby Isaac DM plex; 2110bdd6f66aSToby Isaac PetscErrorCode ierr; 2111bdd6f66aSToby Isaac 2112bdd6f66aSToby Isaac PetscFunctionBegin; 2113bdd6f66aSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 2114bdd6f66aSToby Isaac ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr); 2115bdd6f66aSToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 2116bdd6f66aSToby Isaac PetscFunctionReturn(0); 2117bdd6f66aSToby Isaac } 2118bdd6f66aSToby Isaac 2119089bfe53SSander Arens PetscErrorCode DMPlexComputeBdJacobian_Internal(DM dm, Vec locX, Vec locX_t, PetscReal t, PetscReal X_tShift, Mat Jac, Mat JacP, void *user) 2120089bfe53SSander Arens { 2121089bfe53SSander Arens DM_Plex *mesh = (DM_Plex *) dm->data; 21222d91c981SSander Arens DM dmAux = NULL, plex = NULL; 2123c330f8ffSToby Isaac DMField coordField = NULL; 21242d91c981SSander Arens PetscSection section, globalSection, subSection, sectionAux = NULL; 21252d91c981SSander Arens PetscDS prob, probAux = NULL; 2126089bfe53SSander Arens DMLabel depth; 21272d91c981SSander Arens Vec locA = NULL; 21282d91c981SSander Arens PetscScalar *u = NULL, *u_t = NULL, *a = NULL, *elemMat = NULL; 21294d0b9603SSander Arens PetscInt dim, totDim, totDimAux, numBd, bd, Nf; 2130089bfe53SSander Arens PetscBool isMatISP; 2131c330f8ffSToby Isaac IS facetIS; 2132089bfe53SSander Arens PetscErrorCode ierr; 2133089bfe53SSander Arens 2134089bfe53SSander Arens PetscFunctionBegin; 2135089bfe53SSander Arens ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2136089bfe53SSander Arens ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 2137089bfe53SSander Arens ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatISP);CHKERRQ(ierr); 2138089bfe53SSander Arens ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 2139089bfe53SSander Arens if (isMatISP) { 2140089bfe53SSander Arens ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2141089bfe53SSander Arens } 2142089bfe53SSander Arens ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 2143c330f8ffSToby Isaac ierr = DMLabelGetStratumIS(depth,dim-1,&facetIS);CHKERRQ(ierr); 2144089bfe53SSander Arens ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 2145089bfe53SSander Arens ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 21464d0b9603SSander Arens ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 2147089bfe53SSander Arens ierr = PetscDSGetNumBoundary(prob, &numBd);CHKERRQ(ierr); 21482d91c981SSander Arens ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &locA);CHKERRQ(ierr); 21492d91c981SSander Arens if (locA) { 21502d91c981SSander Arens ierr = VecGetDM(locA, &dmAux);CHKERRQ(ierr); 21512d91c981SSander Arens ierr = DMConvert(dmAux, DMPLEX, &plex);CHKERRQ(ierr); 21522d91c981SSander Arens ierr = DMGetDefaultSection(plex, §ionAux);CHKERRQ(ierr); 21532d91c981SSander Arens ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 21544d0b9603SSander Arens ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 21552d91c981SSander Arens } 21564a3e9fdbSToby Isaac ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 2157089bfe53SSander Arens for (bd = 0; bd < numBd; ++bd) { 2158df1fddb2SMatthew G. Knepley DMBoundaryConditionType type; 2159089bfe53SSander Arens const char *bdLabel; 2160089bfe53SSander Arens DMLabel label; 2161089bfe53SSander Arens IS pointIS; 2162089bfe53SSander Arens const PetscInt *points; 2163089bfe53SSander Arens const PetscInt *values; 2164c330f8ffSToby Isaac PetscInt fieldI, fieldJ, numValues, v, numFaces, face, Nq; 2165089bfe53SSander Arens PetscObject obj; 2166c330f8ffSToby Isaac PetscBool isAffine; 2167c330f8ffSToby Isaac PetscFE fe; 2168089bfe53SSander Arens PetscClassId id; 2169089bfe53SSander Arens 2170df1fddb2SMatthew G. Knepley ierr = PetscDSGetBoundary(prob, bd, &type, NULL, &bdLabel, &fieldI, NULL, NULL, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 21714d0b9603SSander Arens ierr = PetscDSGetDiscretization(prob, fieldI, &obj);CHKERRQ(ierr); 2172089bfe53SSander Arens ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2173df1fddb2SMatthew G. Knepley if ((id != PETSCFE_CLASSID) || (type & DM_BC_ESSENTIAL)) continue; 2174c330f8ffSToby Isaac fe = (PetscFE) obj; 2175089bfe53SSander Arens ierr = DMGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 2176089bfe53SSander Arens for (v = 0; v < numValues; ++v) { 2177c330f8ffSToby Isaac PetscQuadrature qGeom = NULL; 2178c330f8ffSToby Isaac PetscFEGeom *fgeom; 2179c330f8ffSToby Isaac 2180089bfe53SSander Arens ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr); 2181089bfe53SSander Arens if (!pointIS) continue; /* No points with that id on this process */ 2182c330f8ffSToby Isaac { 2183c330f8ffSToby Isaac IS isectIS; 2184c330f8ffSToby Isaac 2185c330f8ffSToby Isaac /* TODO: Special cases of ISIntersect where it is quick to check a prior if one is a superset of the other */ 21864a3e9fdbSToby Isaac ierr = ISIntersect_Caching(facetIS,pointIS,&isectIS);CHKERRQ(ierr); 2187c330f8ffSToby Isaac ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 2188c330f8ffSToby Isaac pointIS = isectIS; 2189089bfe53SSander Arens } 2190c330f8ffSToby Isaac ierr = ISGetLocalSize(pointIS, &numFaces);CHKERRQ(ierr); 2191c330f8ffSToby Isaac ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 2192f99c8401SToby Isaac ierr = PetscMalloc3(numFaces*totDim,&u,locX_t ? numFaces*totDim : 0,&u_t,numFaces*totDim*totDim,&elemMat);CHKERRQ(ierr); 21934d0b9603SSander Arens if (locA) {ierr = PetscMalloc1(numFaces*totDimAux,&a);CHKERRQ(ierr);} 2194c330f8ffSToby Isaac ierr = DMFieldGetFEInvariance(coordField,pointIS,NULL,&isAffine,NULL);CHKERRQ(ierr); 2195c330f8ffSToby Isaac if (isAffine) { 2196c330f8ffSToby Isaac ierr = DMFieldCreateDefaultQuadrature(coordField,pointIS,&qGeom);CHKERRQ(ierr); 2197c330f8ffSToby Isaac } 2198c330f8ffSToby Isaac if (!qGeom) { 2199c330f8ffSToby Isaac ierr = PetscFEGetFaceQuadrature(fe, &qGeom);CHKERRQ(ierr); 2200c330f8ffSToby Isaac ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr); 2201c330f8ffSToby Isaac } 2202c330f8ffSToby Isaac ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 22034a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr); 2204c330f8ffSToby Isaac for (face = 0; face < numFaces; ++face) { 2205c330f8ffSToby Isaac const PetscInt point = points[face], *support, *cone; 2206089bfe53SSander Arens PetscScalar *x = NULL; 22079bfb2fe4SJed Brown PetscInt i, coneSize, faceLoc; 2208089bfe53SSander Arens 22094d0b9603SSander Arens ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 22104d0b9603SSander Arens ierr = DMPlexGetConeSize(dm, support[0], &coneSize);CHKERRQ(ierr); 22114d0b9603SSander Arens ierr = DMPlexGetCone(dm, support[0], &cone);CHKERRQ(ierr); 22124d0b9603SSander Arens for (faceLoc = 0; faceLoc < coneSize; ++faceLoc) if (cone[faceLoc] == point) break; 22134d0b9603SSander Arens if (faceLoc == coneSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of support[0] %d", point, support[0]); 2214f99c8401SToby Isaac fgeom->face[face][0] = faceLoc; 22154d0b9603SSander Arens ierr = DMPlexVecGetClosure(dm, section, locX, support[0], NULL, &x);CHKERRQ(ierr); 22164d0b9603SSander Arens for (i = 0; i < totDim; ++i) u[face*totDim+i] = x[i]; 22174d0b9603SSander Arens ierr = DMPlexVecRestoreClosure(dm, section, locX, support[0], NULL, &x);CHKERRQ(ierr); 2218089bfe53SSander Arens if (locX_t) { 22194d0b9603SSander Arens ierr = DMPlexVecGetClosure(dm, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr); 22204d0b9603SSander Arens for (i = 0; i < totDim; ++i) u_t[face*totDim+i] = x[i]; 22214d0b9603SSander Arens ierr = DMPlexVecRestoreClosure(dm, section, locX_t, support[0], NULL, &x);CHKERRQ(ierr); 2222089bfe53SSander Arens } 22232d91c981SSander Arens if (locA) { 22244d0b9603SSander Arens ierr = DMPlexVecGetClosure(plex, sectionAux, locA, support[0], NULL, &x);CHKERRQ(ierr); 22254d0b9603SSander Arens for (i = 0; i < totDimAux; ++i) a[face*totDimAux+i] = x[i]; 22264d0b9603SSander Arens ierr = DMPlexVecRestoreClosure(plex, sectionAux, locA, support[0], NULL, &x);CHKERRQ(ierr); 22272d91c981SSander Arens } 2228089bfe53SSander Arens } 22294d0b9603SSander Arens ierr = PetscMemzero(elemMat, numFaces*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 2230089bfe53SSander Arens { 2231089bfe53SSander Arens PetscFE fe; 2232c330f8ffSToby Isaac PetscInt Nb; 2233089bfe53SSander Arens /* Conforming batches */ 2234089bfe53SSander Arens PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 2235089bfe53SSander Arens /* Remainder */ 2236c330f8ffSToby Isaac PetscFEGeom *chunkGeom = NULL; 2237089bfe53SSander Arens PetscInt Nr, offset; 2238089bfe53SSander Arens 22394d0b9603SSander Arens ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 2240089bfe53SSander Arens ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 2241089bfe53SSander Arens ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 2242c330f8ffSToby Isaac blockSize = Nb; 2243089bfe53SSander Arens batchSize = numBlocks * blockSize; 2244089bfe53SSander Arens ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 2245089bfe53SSander Arens numChunks = numFaces / (numBatches*batchSize); 2246089bfe53SSander Arens Ne = numChunks*numBatches*batchSize; 2247089bfe53SSander Arens Nr = numFaces % (numBatches*batchSize); 2248089bfe53SSander Arens offset = numFaces - Nr; 2249c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(fgeom,0,offset,&chunkGeom);CHKERRQ(ierr); 2250089bfe53SSander Arens for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 2251c330f8ffSToby Isaac ierr = PetscFEIntegrateBdJacobian(fe, prob, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr); 2252089bfe53SSander Arens } 2253c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr); 2254c330f8ffSToby Isaac for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 2255c330f8ffSToby Isaac ierr = PetscFEIntegrateBdJacobian(fe, prob, fieldI, fieldJ, Nr, chunkGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, a ? &a[offset*totDimAux] : NULL, t, X_tShift, &elemMat[offset*totDim*totDim]);CHKERRQ(ierr); 2256089bfe53SSander Arens } 2257c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(fgeom,offset,numFaces,&chunkGeom);CHKERRQ(ierr); 2258c330f8ffSToby Isaac } 2259c330f8ffSToby Isaac for (face = 0; face < numFaces; ++face) { 2260c330f8ffSToby Isaac const PetscInt point = points[face], *support; 2261089bfe53SSander Arens 22624d0b9603SSander Arens if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(point, "BdJacobian", totDim, totDim, &elemMat[face*totDim*totDim]);CHKERRQ(ierr);} 22634d0b9603SSander Arens ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 2264089bfe53SSander Arens if (!isMatISP) { 22654d0b9603SSander Arens ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, support[0], &elemMat[face*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2266089bfe53SSander Arens } else { 2267089bfe53SSander Arens Mat lJ; 2268089bfe53SSander Arens 2269089bfe53SSander Arens ierr = MatISGetLocalMat(JacP,&lJ);CHKERRQ(ierr); 22704d0b9603SSander Arens ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, support[0], &elemMat[face*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2271089bfe53SSander Arens } 2272089bfe53SSander Arens } 22734a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,pointIS,qGeom,PETSC_TRUE,&fgeom);CHKERRQ(ierr); 2274c330f8ffSToby Isaac ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 2275f99c8401SToby Isaac ierr = PetscFree3(u,u_t,elemMat);CHKERRQ(ierr); 2276089bfe53SSander Arens ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 2277089bfe53SSander Arens ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 22781c46aac1SSander Arens if (locA) {ierr = PetscFree(a);CHKERRQ(ierr);} 22792d91c981SSander Arens } 2280089bfe53SSander Arens } 2281c330f8ffSToby Isaac ierr = ISDestroy(&facetIS);CHKERRQ(ierr); 22821c46aac1SSander Arens if (plex) {ierr = DMDestroy(&plex);CHKERRQ(ierr);} 2283089bfe53SSander Arens PetscFunctionReturn(0); 2284089bfe53SSander Arens } 2285089bfe53SSander Arens 2286f7e6ed9bSMatthew G. Knepley /* 2287f7e6ed9bSMatthew G. Knepley We always assemble JacP, and if the matrix is different from Jac and two different sets of point functions are provided, we also assemble Jac 2288f7e6ed9bSMatthew G. Knepley 2289f7e6ed9bSMatthew G. Knepley X - The local solution vector 2290f7e6ed9bSMatthew G. Knepley X_t - The local solution time derviative vector, or NULL 2291f7e6ed9bSMatthew G. Knepley */ 2292*6f158342SMatthew G. Knepley PetscErrorCode DMPlexComputeJacobian_Patch_Internal(DM dm, PetscSection section, PetscSection globalSection, IS cellIS, 2293f7e6ed9bSMatthew G. Knepley PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Mat Jac, Mat JacP, void *ctx) 2294f7e6ed9bSMatthew G. Knepley { 2295f7e6ed9bSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2296f7e6ed9bSMatthew G. Knepley const char *name = "Jacobian", *nameP = "JacobianPre"; 2297*6f158342SMatthew G. Knepley DM dmAux = NULL; 2298f7e6ed9bSMatthew G. Knepley PetscDS prob, probAux = NULL; 2299f7e6ed9bSMatthew G. Knepley PetscSection sectionAux = NULL; 2300*6f158342SMatthew G. Knepley Vec A; 2301*6f158342SMatthew G. Knepley DMField coordField; 2302*6f158342SMatthew G. Knepley PetscFEGeom *cgeomFEM; 2303*6f158342SMatthew G. Knepley PetscQuadrature qGeom = NULL; 2304f7e6ed9bSMatthew G. Knepley Mat J = Jac, JP = JacP; 2305*6f158342SMatthew G. Knepley PetscScalar *work, *u = NULL, *u_t = NULL, *a = NULL, *elemMat = NULL, *elemMatP = NULL, *elemMatD = NULL; 2306*6f158342SMatthew G. Knepley PetscBool hasJac, hasPrec, hasDyn, isAffine, assembleJac, isMatIS, isMatISP, *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE; 2307*6f158342SMatthew G. Knepley const PetscInt *cells; 2308*6f158342SMatthew G. Knepley PetscInt Nf, fieldI, fieldJ, numCells, cStart, cEnd, numChunks, chunkSize, chunk, totDim, totDimAux = 0, sz, wsz, off = 0, offCell = 0; 2309f7e6ed9bSMatthew G. Knepley PetscErrorCode ierr; 2310f7e6ed9bSMatthew G. Knepley 2311f7e6ed9bSMatthew G. Knepley PetscFunctionBegin; 2312f7e6ed9bSMatthew G. Knepley CHKMEMQ; 2313*6f158342SMatthew G. Knepley ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr); 2314*6f158342SMatthew G. Knepley ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 2315f7e6ed9bSMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 2316f7e6ed9bSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 2317f7e6ed9bSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 2318f7e6ed9bSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 2319f7e6ed9bSMatthew G. Knepley if (dmAux) { 2320f7e6ed9bSMatthew G. Knepley ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 2321f7e6ed9bSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 2322f7e6ed9bSMatthew G. Knepley } 2323f7e6ed9bSMatthew G. Knepley /* Get flags */ 2324f7e6ed9bSMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 2325f7e6ed9bSMatthew G. Knepley ierr = DMGetWorkArray(dm, Nf, MPIU_BOOL, &isFE);CHKERRQ(ierr); 2326f7e6ed9bSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 2327f7e6ed9bSMatthew G. Knepley PetscObject disc; 2328f7e6ed9bSMatthew G. Knepley PetscClassId id; 2329f7e6ed9bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, &disc);CHKERRQ(ierr); 2330f7e6ed9bSMatthew G. Knepley ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 2331f7e6ed9bSMatthew G. Knepley if (id == PETSCFE_CLASSID) {hasFE = PETSC_TRUE; isFE[fieldI] = PETSC_TRUE;} 2332f7e6ed9bSMatthew G. Knepley else if (id == PETSCFV_CLASSID) {hasFV = PETSC_TRUE; isFE[fieldI] = PETSC_FALSE;} 2333f7e6ed9bSMatthew G. Knepley } 2334f7e6ed9bSMatthew G. Knepley ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr); 2335f7e6ed9bSMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr); 2336f7e6ed9bSMatthew G. Knepley ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr); 2337f7e6ed9bSMatthew G. Knepley assembleJac = hasJac && hasPrec && (Jac != JacP) ? PETSC_TRUE : PETSC_FALSE; 2338f7e6ed9bSMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE; 2339f7e6ed9bSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) Jac, MATIS, &isMatIS);CHKERRQ(ierr); 2340f7e6ed9bSMatthew G. Knepley ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatISP);CHKERRQ(ierr); 2341f7e6ed9bSMatthew G. Knepley /* Setup input data and temp arrays (should be DMGetWorkArray) */ 2342f7e6ed9bSMatthew G. Knepley if (isMatISP || isMatISP) {ierr = DMPlexGetSubdomainSection(dm, &globalSection);CHKERRQ(ierr);} 2343f7e6ed9bSMatthew G. Knepley if (isMatIS) {ierr = MatISGetLocalMat(Jac, &J);CHKERRQ(ierr);} 2344f7e6ed9bSMatthew G. Knepley if (isMatISP) {ierr = MatISGetLocalMat(JacP, &JP);CHKERRQ(ierr);} 2345f7e6ed9bSMatthew G. Knepley if (hasFV) {ierr = MatSetOption(JP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE);CHKERRQ(ierr);} /* No allocated space for FV stuff, so ignore the zero entries */ 2346f7e6ed9bSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 2347f7e6ed9bSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 2348f7e6ed9bSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 2349f7e6ed9bSMatthew G. Knepley if (probAux) {ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr);} 2350f7e6ed9bSMatthew G. Knepley CHKMEMQ; 2351f7e6ed9bSMatthew G. Knepley /* Compute batch sizes */ 2352f7e6ed9bSMatthew G. Knepley if (isFE[0]) { 2353f7e6ed9bSMatthew G. Knepley PetscFE fe; 2354f7e6ed9bSMatthew G. Knepley PetscQuadrature q; 2355f7e6ed9bSMatthew G. Knepley PetscInt numQuadPoints, numBatches, batchSize, numBlocks, blockSize, Nb; 2356f7e6ed9bSMatthew G. Knepley 2357f7e6ed9bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr); 2358f7e6ed9bSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 2359f7e6ed9bSMatthew G. Knepley ierr = PetscQuadratureGetData(q, NULL, NULL, &numQuadPoints, NULL, NULL);CHKERRQ(ierr); 2360f7e6ed9bSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 2361f7e6ed9bSMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 2362f7e6ed9bSMatthew G. Knepley blockSize = Nb*numQuadPoints; 2363f7e6ed9bSMatthew G. Knepley batchSize = numBlocks * blockSize; 2364f7e6ed9bSMatthew G. Knepley chunkSize = numBatches * batchSize; 2365f7e6ed9bSMatthew G. Knepley numChunks = numCells / chunkSize + numCells % chunkSize; 2366f7e6ed9bSMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 2367f7e6ed9bSMatthew G. Knepley } else { 2368f7e6ed9bSMatthew G. Knepley chunkSize = numCells; 2369f7e6ed9bSMatthew G. Knepley numChunks = 1; 2370f7e6ed9bSMatthew G. Knepley } 2371f7e6ed9bSMatthew G. Knepley /* Get work space */ 2372f7e6ed9bSMatthew G. Knepley wsz = (((X?1:0) + (X_t?1:0) + (dmAux?1:0))*totDim + ((hasJac?1:0) + (hasPrec?1:0) + (hasDyn?1:0))*totDim*totDim)*chunkSize; 2373f7e6ed9bSMatthew G. Knepley ierr = DMGetWorkArray(dm, wsz, MPIU_SCALAR, &work);CHKERRQ(ierr); 2374f7e6ed9bSMatthew G. Knepley ierr = PetscMemzero(work, wsz * sizeof(PetscScalar));CHKERRQ(ierr); 2375f7e6ed9bSMatthew G. Knepley off = 0; 2376f7e6ed9bSMatthew G. Knepley u = X ? (sz = chunkSize*totDim, off += sz, work+off-sz) : NULL; 2377f7e6ed9bSMatthew G. Knepley u_t = X_t ? (sz = chunkSize*totDim, off += sz, work+off-sz) : NULL; 2378f7e6ed9bSMatthew G. Knepley a = dmAux ? (sz = chunkSize*totDimAux, off += sz, work+off-sz) : NULL; 2379f7e6ed9bSMatthew G. Knepley elemMat = hasJac ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL; 2380f7e6ed9bSMatthew G. Knepley elemMatP = hasPrec ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL; 2381f7e6ed9bSMatthew G. Knepley elemMatD = hasDyn ? (sz = chunkSize*totDim*totDim, off += sz, work+off-sz) : NULL; 2382f7e6ed9bSMatthew G. Knepley if (off != wsz) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Error is workspace size %D should be %D", off, wsz); 2383*6f158342SMatthew G. Knepley /* Setup geometry */ 2384*6f158342SMatthew G. Knepley ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 2385*6f158342SMatthew G. Knepley ierr = DMFieldGetFEInvariance(coordField, cellIS, NULL, &isAffine, NULL);CHKERRQ(ierr); 2386*6f158342SMatthew G. Knepley if (isAffine) {ierr = DMFieldCreateDefaultQuadrature(coordField, cellIS, &qGeom);CHKERRQ(ierr);} 2387*6f158342SMatthew G. Knepley if (!qGeom) { 2388*6f158342SMatthew G. Knepley PetscFE fe; 2389*6f158342SMatthew G. Knepley 2390*6f158342SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, 0, (PetscObject *) &fe);CHKERRQ(ierr); 2391*6f158342SMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &qGeom);CHKERRQ(ierr); 2392*6f158342SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) qGeom);CHKERRQ(ierr); 2393*6f158342SMatthew G. Knepley } 2394*6f158342SMatthew G. Knepley ierr = DMSNESGetFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM);CHKERRQ(ierr); 2395f7e6ed9bSMatthew G. Knepley /* Compute volume integrals */ 2396f7e6ed9bSMatthew G. Knepley if (assembleJac) {ierr = MatZeroEntries(J);CHKERRQ(ierr);} 2397f7e6ed9bSMatthew G. Knepley ierr = MatZeroEntries(JP);CHKERRQ(ierr); 2398f7e6ed9bSMatthew G. Knepley for (chunk = 0; chunk < numChunks; ++chunk, offCell += chunkSize) { 2399f7e6ed9bSMatthew G. Knepley const PetscInt Ncell = PetscMin(chunkSize, numCells - offCell); 2400*6f158342SMatthew G. Knepley PetscFEGeom *chunkGeom = NULL; 2401f7e6ed9bSMatthew G. Knepley PetscInt c; 2402f7e6ed9bSMatthew G. Knepley 2403f7e6ed9bSMatthew G. Knepley /* Extract values */ 2404f7e6ed9bSMatthew G. Knepley for (c = 0; c < Ncell; ++c) { 2405f7e6ed9bSMatthew G. Knepley const PetscInt cell = cells ? cells[c+offCell] : c+offCell; 2406f7e6ed9bSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 2407f7e6ed9bSMatthew G. Knepley PetscInt i; 2408f7e6ed9bSMatthew G. Knepley 2409f7e6ed9bSMatthew G. Knepley if (X) { 2410f7e6ed9bSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 2411f7e6ed9bSMatthew G. Knepley for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 2412f7e6ed9bSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 2413f7e6ed9bSMatthew G. Knepley } 2414f7e6ed9bSMatthew G. Knepley if (X_t) { 2415f7e6ed9bSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 2416f7e6ed9bSMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[c*totDim+i] = x_t[i]; 2417f7e6ed9bSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 2418f7e6ed9bSMatthew G. Knepley } 2419f7e6ed9bSMatthew G. Knepley if (dmAux) { 2420f7e6ed9bSMatthew G. Knepley ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 2421f7e6ed9bSMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 2422f7e6ed9bSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 2423f7e6ed9bSMatthew G. Knepley } 2424f7e6ed9bSMatthew G. Knepley } 2425f7e6ed9bSMatthew G. Knepley CHKMEMQ; 2426f7e6ed9bSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 2427f7e6ed9bSMatthew G. Knepley PetscFE fe; 2428f7e6ed9bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 2429*6f158342SMatthew G. Knepley ierr = PetscFEGeomGetChunk(cgeomFEM,0,Ncell,&chunkGeom);CHKERRQ(ierr); 2430f7e6ed9bSMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 2431*6f158342SMatthew G. Knepley if (hasJac) {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Ncell, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr);} 2432*6f158342SMatthew G. Knepley if (hasPrec) {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_PRE, fieldI, fieldJ, Ncell, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatP);CHKERRQ(ierr);} 2433*6f158342SMatthew G. Knepley if (hasDyn) {ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Ncell, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr);} 2434f7e6ed9bSMatthew G. Knepley } 2435f7e6ed9bSMatthew G. Knepley /* For finite volume, add the identity */ 2436f7e6ed9bSMatthew G. Knepley if (!isFE[fieldI]) { 2437f7e6ed9bSMatthew G. Knepley PetscFV fv; 2438f7e6ed9bSMatthew G. Knepley PetscInt eOffset = 0, Nc, fc, foff; 2439f7e6ed9bSMatthew G. Knepley 2440f7e6ed9bSMatthew G. Knepley ierr = PetscDSGetFieldOffset(prob, fieldI, &foff);CHKERRQ(ierr); 2441f7e6ed9bSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fv);CHKERRQ(ierr); 2442f7e6ed9bSMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 2443f7e6ed9bSMatthew G. Knepley for (c = 0; c < chunkSize; ++c, eOffset += totDim*totDim) { 2444f7e6ed9bSMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 2445f7e6ed9bSMatthew G. Knepley const PetscInt i = foff + fc; 2446f7e6ed9bSMatthew G. Knepley if (hasJac) {elemMat [eOffset+i*totDim+i] = 1.0;} 2447f7e6ed9bSMatthew G. Knepley if (hasPrec) {elemMatP[eOffset+i*totDim+i] = 1.0;} 2448f7e6ed9bSMatthew G. Knepley } 2449f7e6ed9bSMatthew G. Knepley } 2450f7e6ed9bSMatthew G. Knepley } 2451f7e6ed9bSMatthew G. Knepley } 2452f7e6ed9bSMatthew G. Knepley CHKMEMQ; 2453f7e6ed9bSMatthew G. Knepley /* Add contribution from X_t */ 2454f7e6ed9bSMatthew G. Knepley if (hasDyn) {for (c = 0; c < chunkSize*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c];} 2455f7e6ed9bSMatthew G. Knepley /* Insert values into matrix */ 2456f7e6ed9bSMatthew G. Knepley for (c = 0; c < Ncell; ++c) { 2457f7e6ed9bSMatthew G. Knepley const PetscInt cell = cells ? cells[c+offCell] : c+offCell; 2458f7e6ed9bSMatthew G. Knepley if (mesh->printFEM > 1) { 2459f7e6ed9bSMatthew G. Knepley if (hasJac) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[(c-cStart)*totDim*totDim]);CHKERRQ(ierr);} 2460f7e6ed9bSMatthew G. Knepley if (hasPrec) {ierr = DMPrintCellMatrix(cell, nameP, totDim, totDim, &elemMatP[(c-cStart)*totDim*totDim]);CHKERRQ(ierr);} 2461f7e6ed9bSMatthew G. Knepley } 2462f7e6ed9bSMatthew G. Knepley if (assembleJac) {ierr = DMPlexMatSetClosure(dm, section, globalSection, Jac, cell, &elemMat[(c-cStart)*totDim*totDim], ADD_VALUES);CHKERRQ(ierr);} 2463f7e6ed9bSMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JP, cell, &elemMat[(c-cStart)*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2464f7e6ed9bSMatthew G. Knepley } 2465f7e6ed9bSMatthew G. Knepley CHKMEMQ; 2466f7e6ed9bSMatthew G. Knepley } 2467f7e6ed9bSMatthew G. Knepley /* Cleanup */ 2468*6f158342SMatthew G. Knepley ierr = DMSNESRestoreFEGeom(coordField, cellIS, qGeom, PETSC_FALSE, &cgeomFEM);CHKERRQ(ierr); 2469*6f158342SMatthew G. Knepley ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 2470f7e6ed9bSMatthew G. Knepley if (hasFV) {ierr = MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE);CHKERRQ(ierr);} 2471f7e6ed9bSMatthew G. Knepley ierr = DMRestoreWorkArray(dm, Nf, PETSC_BOOL, &isFE);CHKERRQ(ierr); 2472f7e6ed9bSMatthew G. Knepley ierr = DMRestoreWorkArray(dm, ((1 + (X_t?1:0) + (dmAux?1:0))*totDim + ((hasJac?1:0) + (hasPrec?1:0) + (hasDyn?1:0))*totDim*totDim)*chunkSize, PETSC_SCALAR, &work);CHKERRQ(ierr); 2473f7e6ed9bSMatthew G. Knepley /* Compute boundary integrals */ 24742cf2a403SMatthew G. Knepley /* ierr = DMPlexComputeBdJacobian_Internal(dm, X, X_t, t, X_tShift, Jac, JacP, ctx);CHKERRQ(ierr); */ 2475f7e6ed9bSMatthew G. Knepley /* Assemble matrix */ 2476f7e6ed9bSMatthew G. Knepley if (assembleJac) {ierr = MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);ierr = MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);} 2477f7e6ed9bSMatthew G. Knepley ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2478f7e6ed9bSMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 2479f7e6ed9bSMatthew G. Knepley CHKMEMQ; 2480f7e6ed9bSMatthew G. Knepley PetscFunctionReturn(0); 2481f7e6ed9bSMatthew G. Knepley } 2482f7e6ed9bSMatthew G. Knepley 24834a3e9fdbSToby Isaac PetscErrorCode DMPlexComputeJacobian_Internal(DM dm, IS cellIS, PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Mat Jac, Mat JacP,void *user) 248424cdb843SMatthew G. Knepley { 248524cdb843SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 248624cdb843SMatthew G. Knepley const char *name = "Jacobian"; 2487f7ed7b21SMatthew G. Knepley DM dmAux, plex; 2488c330f8ffSToby Isaac Vec A; 2489c330f8ffSToby Isaac DMField coordField; 249024cdb843SMatthew G. Knepley PetscDS prob, probAux = NULL; 2491be36d101SStefano Zampini PetscSection section, globalSection, subSection, sectionAux; 2492426ff135SMatthew G. Knepley PetscScalar *elemMat, *elemMatP, *elemMatD, *u, *u_t, *a = NULL; 24939044fa66SMatthew G. Knepley const PetscInt *cells; 24949044fa66SMatthew G. Knepley PetscInt Nf, fieldI, fieldJ; 24959044fa66SMatthew G. Knepley PetscInt totDim, totDimAux, cStart, cEnd, numCells, c; 2496*6f158342SMatthew G. Knepley PetscBool isMatIS, isMatISP, hasJac, hasPrec, hasDyn, hasFV = PETSC_FALSE; 249724cdb843SMatthew G. Knepley PetscErrorCode ierr; 249824cdb843SMatthew G. Knepley 249924cdb843SMatthew G. Knepley PetscFunctionBegin; 250024cdb843SMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 250124cdb843SMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 2502be36d101SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatISP);CHKERRQ(ierr); 250324cdb843SMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 25045bf53532SMatthew G. Knepley if (isMatISP) {ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr);} 250524cdb843SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 250624cdb843SMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 2507efc10488SMatthew G. Knepley ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr); 250855ad3c34SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr); 2509426ff135SMatthew G. Knepley ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr); 2510426ff135SMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE; 251124cdb843SMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 25124a3e9fdbSToby Isaac ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr); 25139044fa66SMatthew G. Knepley ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 251424cdb843SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 251524cdb843SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 251624cdb843SMatthew G. Knepley if (dmAux) { 2517f7ed7b21SMatthew G. Knepley ierr = DMConvert(dmAux, DMPLEX, &plex);CHKERRQ(ierr); 2518f7ed7b21SMatthew G. Knepley ierr = DMGetDefaultSection(plex, §ionAux);CHKERRQ(ierr); 251924cdb843SMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 252024cdb843SMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 252124cdb843SMatthew G. Knepley } 2522efc10488SMatthew G. Knepley ierr = PetscMalloc5(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,hasJac ? numCells*totDim*totDim : 0,&elemMat,hasPrec ? numCells*totDim*totDim : 0, &elemMatP,hasDyn ? numCells*totDim*totDim : 0, &elemMatD);CHKERRQ(ierr); 252324cdb843SMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 25244a3e9fdbSToby Isaac ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 252524cdb843SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 25269044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 25279044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 252824cdb843SMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 252924cdb843SMatthew G. Knepley PetscInt i; 253024cdb843SMatthew G. Knepley 25319044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 25329044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[cind*totDim+i] = x[i]; 25339044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 253424cdb843SMatthew G. Knepley if (X_t) { 25359044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 25369044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[cind*totDim+i] = x_t[i]; 25379044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 253824cdb843SMatthew G. Knepley } 253924cdb843SMatthew G. Knepley if (dmAux) { 25409044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 25419044fa66SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[cind*totDimAux+i] = x[i]; 25429044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 254324cdb843SMatthew G. Knepley } 254424cdb843SMatthew G. Knepley } 2545efc10488SMatthew G. Knepley if (hasJac) {ierr = PetscMemzero(elemMat, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);} 254655ad3c34SMatthew G. Knepley if (hasPrec) {ierr = PetscMemzero(elemMatP, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);} 2547426ff135SMatthew G. Knepley if (hasDyn) {ierr = PetscMemzero(elemMatD, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);} 254824cdb843SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 25495244db28SMatthew G. Knepley PetscClassId id; 255024cdb843SMatthew G. Knepley PetscFE fe; 2551c330f8ffSToby Isaac PetscQuadrature qGeom = NULL; 2552c330f8ffSToby Isaac PetscInt Nb; 255324cdb843SMatthew G. Knepley /* Conforming batches */ 255424cdb843SMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 255524cdb843SMatthew G. Knepley /* Remainder */ 2556c330f8ffSToby Isaac PetscInt Nr, offset, Nq; 2557c330f8ffSToby Isaac PetscBool isAffine; 2558c330f8ffSToby Isaac PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL; 255924cdb843SMatthew G. Knepley 256024cdb843SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 25615244db28SMatthew G. Knepley ierr = PetscObjectGetClassId((PetscObject) fe, &id);CHKERRQ(ierr); 25625244db28SMatthew G. Knepley if (id == PETSCFV_CLASSID) {hasFV = PETSC_TRUE; continue;} 256324cdb843SMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 256424cdb843SMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 2565c330f8ffSToby Isaac ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr); 2566c330f8ffSToby Isaac if (isAffine) { 2567c330f8ffSToby Isaac ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr); 2568c330f8ffSToby Isaac } 2569c330f8ffSToby Isaac if (!qGeom) { 2570c330f8ffSToby Isaac ierr = PetscFEGetQuadrature(fe,&qGeom);CHKERRQ(ierr); 2571c330f8ffSToby Isaac ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr); 2572c330f8ffSToby Isaac } 2573c330f8ffSToby Isaac ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 25744a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 2575c330f8ffSToby Isaac blockSize = Nb; 257624cdb843SMatthew G. Knepley batchSize = numBlocks * blockSize; 257724cdb843SMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 257824cdb843SMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 257924cdb843SMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 258024cdb843SMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 258124cdb843SMatthew G. Knepley offset = numCells - Nr; 2582c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 2583c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr); 258424cdb843SMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 2585efc10488SMatthew G. Knepley if (hasJac) { 2586c330f8ffSToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr); 2587c330f8ffSToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMat[offset*totDim*totDim]);CHKERRQ(ierr); 2588efc10488SMatthew G. Knepley } 258955ad3c34SMatthew G. Knepley if (hasPrec) { 2590c330f8ffSToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_PRE, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatP);CHKERRQ(ierr); 2591c330f8ffSToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_PRE, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMatP[offset*totDim*totDim]);CHKERRQ(ierr); 2592426ff135SMatthew G. Knepley } 2593426ff135SMatthew G. Knepley if (hasDyn) { 2594c330f8ffSToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr); 2595c330f8ffSToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMatD[offset*totDim*totDim]);CHKERRQ(ierr); 259655ad3c34SMatthew G. Knepley } 259724cdb843SMatthew G. Knepley } 2598c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr); 2599c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 26004a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 2601c330f8ffSToby Isaac ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 260224cdb843SMatthew G. Knepley } 26035bf53532SMatthew G. Knepley /* Add contribution from X_t */ 26049044fa66SMatthew G. Knepley if (hasDyn) {for (c = 0; c < numCells*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c];} 26055244db28SMatthew G. Knepley if (hasFV) { 26065244db28SMatthew G. Knepley PetscClassId id; 26075244db28SMatthew G. Knepley PetscFV fv; 26085244db28SMatthew G. Knepley PetscInt offsetI, NcI, NbI = 1, fc, f; 26095244db28SMatthew G. Knepley 26105244db28SMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 26115244db28SMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fv);CHKERRQ(ierr); 26125244db28SMatthew G. Knepley ierr = PetscDSGetFieldOffset(prob, fieldI, &offsetI);CHKERRQ(ierr); 26135244db28SMatthew G. Knepley ierr = PetscObjectGetClassId((PetscObject) fv, &id);CHKERRQ(ierr); 26145244db28SMatthew G. Knepley if (id != PETSCFV_CLASSID) continue; 26155244db28SMatthew G. Knepley /* Put in the identity */ 26165244db28SMatthew G. Knepley ierr = PetscFVGetNumComponents(fv, &NcI);CHKERRQ(ierr); 26175244db28SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 26189044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 26199044fa66SMatthew G. Knepley const PetscInt eOffset = cind*totDim*totDim; 26205244db28SMatthew G. Knepley for (fc = 0; fc < NcI; ++fc) { 26215244db28SMatthew G. Knepley for (f = 0; f < NbI; ++f) { 26225244db28SMatthew G. Knepley const PetscInt i = offsetI + f*NcI+fc; 26235244db28SMatthew G. Knepley if (hasPrec) { 26245244db28SMatthew G. Knepley if (hasJac) {elemMat[eOffset+i*totDim+i] = 1.0;} 26255244db28SMatthew G. Knepley elemMatP[eOffset+i*totDim+i] = 1.0; 26265244db28SMatthew G. Knepley } else {elemMat[eOffset+i*totDim+i] = 1.0;} 26275244db28SMatthew G. Knepley } 26285244db28SMatthew G. Knepley } 26295244db28SMatthew G. Knepley } 26305244db28SMatthew G. Knepley } 26315244db28SMatthew G. Knepley /* No allocated space for FV stuff, so ignore the zero entries */ 26325244db28SMatthew G. Knepley ierr = MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE);CHKERRQ(ierr); 26335244db28SMatthew G. Knepley } 26345bf53532SMatthew G. Knepley /* Insert values into matrix */ 2635be36d101SStefano Zampini isMatIS = PETSC_FALSE; 2636be36d101SStefano Zampini if (hasPrec && hasJac) { 2637be36d101SStefano Zampini ierr = PetscObjectTypeCompare((PetscObject) JacP, MATIS, &isMatIS);CHKERRQ(ierr); 2638be36d101SStefano Zampini } 2639be36d101SStefano Zampini if (isMatIS && !subSection) { 2640be36d101SStefano Zampini ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr); 2641be36d101SStefano Zampini } 264224cdb843SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 26439044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 26449044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 26459044fa66SMatthew G. Knepley 264655ad3c34SMatthew G. Knepley if (hasPrec) { 2647efc10488SMatthew G. Knepley if (hasJac) { 26489044fa66SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr);} 2649be36d101SStefano Zampini if (!isMatIS) { 26509044fa66SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, Jac, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2651be36d101SStefano Zampini } else { 2652be36d101SStefano Zampini Mat lJ; 2653be36d101SStefano Zampini 2654be36d101SStefano Zampini ierr = MatISGetLocalMat(Jac,&lJ);CHKERRQ(ierr); 26559044fa66SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2656be36d101SStefano Zampini } 2657efc10488SMatthew G. Knepley } 26589044fa66SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMatP[cind*totDim*totDim]);CHKERRQ(ierr);} 2659be36d101SStefano Zampini if (!isMatISP) { 26609044fa66SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, cell, &elemMatP[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 266155ad3c34SMatthew G. Knepley } else { 2662be36d101SStefano Zampini Mat lJ; 2663be36d101SStefano Zampini 2664be36d101SStefano Zampini ierr = MatISGetLocalMat(JacP,&lJ);CHKERRQ(ierr); 26659044fa66SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, cell, &elemMatP[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2666be36d101SStefano Zampini } 2667be36d101SStefano Zampini } else { 26689044fa66SMatthew G. Knepley if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr);} 2669be36d101SStefano Zampini if (!isMatISP) { 26709044fa66SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, globalSection, JacP, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2671be36d101SStefano Zampini } else { 2672be36d101SStefano Zampini Mat lJ; 2673be36d101SStefano Zampini 2674be36d101SStefano Zampini ierr = MatISGetLocalMat(JacP,&lJ);CHKERRQ(ierr); 26759044fa66SMatthew G. Knepley ierr = DMPlexMatSetClosure(dm, section, subSection, lJ, cell, &elemMat[cind*totDim*totDim], ADD_VALUES);CHKERRQ(ierr); 2676be36d101SStefano Zampini } 267724cdb843SMatthew G. Knepley } 267855ad3c34SMatthew G. Knepley } 26799044fa66SMatthew G. Knepley ierr = ISRestorePointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 26805244db28SMatthew G. Knepley if (hasFV) {ierr = MatSetOption(JacP, MAT_IGNORE_ZERO_ENTRIES, PETSC_FALSE);CHKERRQ(ierr);} 2681426ff135SMatthew G. Knepley ierr = PetscFree5(u,u_t,elemMat,elemMatP,elemMatD);CHKERRQ(ierr); 2682f7ed7b21SMatthew G. Knepley if (dmAux) { 2683f7ed7b21SMatthew G. Knepley ierr = PetscFree(a);CHKERRQ(ierr); 2684f7ed7b21SMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 2685f7ed7b21SMatthew G. Knepley } 26865bf53532SMatthew G. Knepley /* Compute boundary integrals */ 2687089bfe53SSander Arens ierr = DMPlexComputeBdJacobian_Internal(dm, X, X_t, t, X_tShift, Jac, JacP, user);CHKERRQ(ierr); 26885bf53532SMatthew G. Knepley /* Assemble matrix */ 2689efc10488SMatthew G. Knepley if (hasJac && hasPrec) { 269082ef7567SMatthew G. Knepley ierr = MatAssemblyBegin(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 269182ef7567SMatthew G. Knepley ierr = MatAssemblyEnd(Jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 269282ef7567SMatthew G. Knepley } 269324cdb843SMatthew G. Knepley ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 269424cdb843SMatthew G. Knepley ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 269524cdb843SMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 269624cdb843SMatthew G. Knepley PetscFunctionReturn(0); 269724cdb843SMatthew G. Knepley } 269824cdb843SMatthew G. Knepley 26994a3e9fdbSToby Isaac PetscErrorCode DMPlexComputeJacobianAction_Internal(DM dm, IS cellIS, PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Vec Y, Vec Z, void *user) 2700a925c78cSMatthew G. Knepley { 2701a925c78cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 2702a925c78cSMatthew G. Knepley const char *name = "Jacobian"; 2703a925c78cSMatthew G. Knepley DM dmAux, plex; 2704c330f8ffSToby Isaac Vec A; 2705a925c78cSMatthew G. Knepley PetscDS prob, probAux = NULL; 2706a925c78cSMatthew G. Knepley PetscQuadrature quad; 2707a925c78cSMatthew G. Knepley PetscSection section, globalSection, sectionAux; 2708a925c78cSMatthew G. Knepley PetscScalar *elemMat, *elemMatD, *u, *u_t, *a = NULL, *y, *z; 27099044fa66SMatthew G. Knepley PetscInt Nf, fieldI, fieldJ; 27104d0b9603SSander Arens PetscInt totDim, totDimAux = 0; 27119044fa66SMatthew G. Knepley const PetscInt *cells; 27129044fa66SMatthew G. Knepley PetscInt cStart, cEnd, numCells, c; 271375b37a90SMatthew G. Knepley PetscBool hasDyn; 2714c330f8ffSToby Isaac DMField coordField; 2715a925c78cSMatthew G. Knepley PetscErrorCode ierr; 2716a925c78cSMatthew G. Knepley 2717a925c78cSMatthew G. Knepley PetscFunctionBegin; 2718a925c78cSMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 2719a925c78cSMatthew G. Knepley ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 2720a925c78cSMatthew G. Knepley ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 2721a925c78cSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 2722a925c78cSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 2723a925c78cSMatthew G. Knepley ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr); 2724a925c78cSMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE; 2725a925c78cSMatthew G. Knepley ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 27264a3e9fdbSToby Isaac ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr); 27279044fa66SMatthew G. Knepley ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 2728a925c78cSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 2729a925c78cSMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 2730a925c78cSMatthew G. Knepley if (dmAux) { 2731a925c78cSMatthew G. Knepley ierr = DMConvert(dmAux, DMPLEX, &plex);CHKERRQ(ierr); 2732a925c78cSMatthew G. Knepley ierr = DMGetDefaultSection(plex, §ionAux);CHKERRQ(ierr); 2733a925c78cSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 2734a925c78cSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 2735a925c78cSMatthew G. Knepley } 2736a925c78cSMatthew G. Knepley ierr = VecSet(Z, 0.0);CHKERRQ(ierr); 2737a925c78cSMatthew G. Knepley ierr = PetscMalloc6(numCells*totDim,&u,X_t ? numCells*totDim : 0,&u_t,numCells*totDim*totDim,&elemMat,hasDyn ? numCells*totDim*totDim : 0, &elemMatD,numCells*totDim,&y,totDim,&z);CHKERRQ(ierr); 2738a925c78cSMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 27394a3e9fdbSToby Isaac ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 2740a925c78cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 27419044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 27429044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 2743a925c78cSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 2744a925c78cSMatthew G. Knepley PetscInt i; 2745a925c78cSMatthew G. Knepley 27469044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 27479044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[cind*totDim+i] = x[i]; 27489044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 2749a925c78cSMatthew G. Knepley if (X_t) { 27509044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 27519044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[cind*totDim+i] = x_t[i]; 27529044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 2753a925c78cSMatthew G. Knepley } 2754a925c78cSMatthew G. Knepley if (dmAux) { 27559044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 27569044fa66SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[cind*totDimAux+i] = x[i]; 27579044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plex, sectionAux, A, cell, NULL, &x);CHKERRQ(ierr); 2758a925c78cSMatthew G. Knepley } 27599044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr); 27609044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) y[cind*totDim+i] = x[i]; 27619044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr); 2762a925c78cSMatthew G. Knepley } 2763a925c78cSMatthew G. Knepley ierr = PetscMemzero(elemMat, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr); 2764a925c78cSMatthew G. Knepley if (hasDyn) {ierr = PetscMemzero(elemMatD, numCells*totDim*totDim * sizeof(PetscScalar));CHKERRQ(ierr);} 2765a925c78cSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 2766a925c78cSMatthew G. Knepley PetscFE fe; 2767c330f8ffSToby Isaac PetscInt Nb; 2768a925c78cSMatthew G. Knepley /* Conforming batches */ 2769a925c78cSMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 2770a925c78cSMatthew G. Knepley /* Remainder */ 2771c330f8ffSToby Isaac PetscInt Nr, offset, Nq; 2772c330f8ffSToby Isaac PetscQuadrature qGeom = NULL; 2773c330f8ffSToby Isaac PetscBool isAffine; 2774c330f8ffSToby Isaac PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL; 2775a925c78cSMatthew G. Knepley 2776a925c78cSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 2777a925c78cSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 2778a925c78cSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 2779a925c78cSMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 2780c330f8ffSToby Isaac ierr = DMFieldGetFEInvariance(coordField,cellIS,NULL,&isAffine,NULL);CHKERRQ(ierr); 2781c330f8ffSToby Isaac if (isAffine) { 2782c330f8ffSToby Isaac ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr); 2783c330f8ffSToby Isaac } 2784c330f8ffSToby Isaac if (!qGeom) { 2785c330f8ffSToby Isaac ierr = PetscFEGetQuadrature(fe,&qGeom);CHKERRQ(ierr); 2786c330f8ffSToby Isaac ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr); 2787c330f8ffSToby Isaac } 2788c330f8ffSToby Isaac ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 27894a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 2790c330f8ffSToby Isaac blockSize = Nb; 2791a925c78cSMatthew G. Knepley batchSize = numBlocks * blockSize; 2792a925c78cSMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 2793a925c78cSMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 2794a925c78cSMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 2795a925c78cSMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 2796a925c78cSMatthew G. Knepley offset = numCells - Nr; 2797c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 2798c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr); 2799a925c78cSMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 2800f99c8401SToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr); 2801f99c8401SToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMat[offset*totDim*totDim]);CHKERRQ(ierr); 2802a925c78cSMatthew G. Knepley if (hasDyn) { 2803f99c8401SToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr); 2804f99c8401SToby Isaac ierr = PetscFEIntegrateJacobian(fe, prob, PETSCFE_JACOBIAN_DYN, fieldI, fieldJ, Nr, remGeom, &u[offset*totDim], u_t ? &u_t[offset*totDim] : NULL, probAux, &a[offset*totDimAux], t, X_tShift, &elemMatD[offset*totDim*totDim]);CHKERRQ(ierr); 2805a925c78cSMatthew G. Knepley } 2806a925c78cSMatthew G. Knepley } 2807c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr); 2808c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 28094a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 2810c330f8ffSToby Isaac ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 2811a925c78cSMatthew G. Knepley } 2812a925c78cSMatthew G. Knepley if (hasDyn) { 28139044fa66SMatthew G. Knepley for (c = 0; c < numCells*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c]; 2814a925c78cSMatthew G. Knepley } 2815a925c78cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 28169044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 28179044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 2818a925c78cSMatthew G. Knepley const PetscBLASInt M = totDim, one = 1; 2819a925c78cSMatthew G. Knepley const PetscScalar a = 1.0, b = 0.0; 2820a925c78cSMatthew G. Knepley 28219044fa66SMatthew G. Knepley PetscStackCallBLAS("BLASgemv", BLASgemv_("N", &M, &M, &a, &elemMat[cind*totDim*totDim], &M, &y[cind*totDim], &one, &b, z, &one)); 2822a925c78cSMatthew G. Knepley if (mesh->printFEM > 1) { 28239044fa66SMatthew G. Knepley ierr = DMPrintCellMatrix(c, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr); 28249044fa66SMatthew G. Knepley ierr = DMPrintCellVector(c, "Y", totDim, &y[cind*totDim]);CHKERRQ(ierr); 2825a925c78cSMatthew G. Knepley ierr = DMPrintCellVector(c, "Z", totDim, z);CHKERRQ(ierr); 2826a925c78cSMatthew G. Knepley } 28279044fa66SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, Z, cell, z, ADD_VALUES);CHKERRQ(ierr); 2828a925c78cSMatthew G. Knepley } 2829a925c78cSMatthew G. Knepley ierr = PetscFree6(u,u_t,elemMat,elemMatD,y,z);CHKERRQ(ierr); 2830a925c78cSMatthew G. Knepley if (dmAux) { 2831a925c78cSMatthew G. Knepley ierr = PetscFree(a);CHKERRQ(ierr); 2832a925c78cSMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 2833a925c78cSMatthew G. Knepley } 2834a925c78cSMatthew G. Knepley if (mesh->printFEM) { 2835a925c78cSMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "Z:\n");CHKERRQ(ierr); 2836a925c78cSMatthew G. Knepley ierr = VecView(Z, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 2837a925c78cSMatthew G. Knepley } 2838a925c78cSMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 2839a925c78cSMatthew G. Knepley PetscFunctionReturn(0); 2840a925c78cSMatthew G. Knepley } 2841a925c78cSMatthew G. Knepley 284224cdb843SMatthew G. Knepley /*@ 284324cdb843SMatthew G. Knepley DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 284424cdb843SMatthew G. Knepley 284524cdb843SMatthew G. Knepley Input Parameters: 284624cdb843SMatthew G. Knepley + dm - The mesh 284724cdb843SMatthew G. Knepley . X - Local input vector 284824cdb843SMatthew G. Knepley - user - The user context 284924cdb843SMatthew G. Knepley 285024cdb843SMatthew G. Knepley Output Parameter: 285124cdb843SMatthew G. Knepley . Jac - Jacobian matrix 285224cdb843SMatthew G. Knepley 285324cdb843SMatthew G. Knepley Note: 285424cdb843SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 285524cdb843SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 285624cdb843SMatthew G. Knepley 285724cdb843SMatthew G. Knepley Level: developer 285824cdb843SMatthew G. Knepley 285924cdb843SMatthew G. Knepley .seealso: FormFunctionLocal() 286024cdb843SMatthew G. Knepley @*/ 286124cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user) 286224cdb843SMatthew G. Knepley { 28636da023fcSToby Isaac DM plex; 2864f04eb4edSMatthew G. Knepley PetscDS prob; 28654a3e9fdbSToby Isaac IS cellIS; 2866f04eb4edSMatthew G. Knepley PetscBool hasJac, hasPrec; 28674a3e9fdbSToby Isaac PetscInt depth; 286824cdb843SMatthew G. Knepley PetscErrorCode ierr; 286924cdb843SMatthew G. Knepley 287024cdb843SMatthew G. Knepley PetscFunctionBegin; 28716da023fcSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 28724a3e9fdbSToby Isaac ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 2873aeadca18SToby Isaac ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr); 28749044fa66SMatthew G. Knepley if (!cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr);} 2875f04eb4edSMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 2876f04eb4edSMatthew G. Knepley ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr); 2877f04eb4edSMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr); 2878f04eb4edSMatthew G. Knepley if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);} 2879f04eb4edSMatthew G. Knepley ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 28804a3e9fdbSToby Isaac ierr = DMPlexComputeJacobian_Internal(plex, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr); 28814a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 28829a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 288324cdb843SMatthew G. Knepley PetscFunctionReturn(0); 288424cdb843SMatthew G. Knepley } 28851878804aSMatthew G. Knepley 2886a925c78cSMatthew G. Knepley /*@ 2887a925c78cSMatthew G. Knepley DMPlexSNESComputeJacobianActionFEM - Form the local portion of the Jacobian action Z = J(X) Y at the local solution X using pointwise functions specified by the user. 2888a925c78cSMatthew G. Knepley 2889a925c78cSMatthew G. Knepley Input Parameters: 2890a925c78cSMatthew G. Knepley + dm - The mesh 2891a925c78cSMatthew G. Knepley . X - Local solution vector 2892a925c78cSMatthew G. Knepley . Y - Local input vector 2893a925c78cSMatthew G. Knepley - user - The user context 2894a925c78cSMatthew G. Knepley 2895a925c78cSMatthew G. Knepley Output Parameter: 2896a925c78cSMatthew G. Knepley . Z - Local output vector 2897a925c78cSMatthew G. Knepley 2898a925c78cSMatthew G. Knepley Note: 2899a925c78cSMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 2900a925c78cSMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 2901a925c78cSMatthew G. Knepley 2902a925c78cSMatthew G. Knepley Level: developer 2903a925c78cSMatthew G. Knepley 2904a925c78cSMatthew G. Knepley .seealso: FormFunctionLocal() 2905a925c78cSMatthew G. Knepley @*/ 2906a925c78cSMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianActionFEM(DM dm, Vec X, Vec Y, Vec Z, void *user) 2907a925c78cSMatthew G. Knepley { 2908a925c78cSMatthew G. Knepley DM plex; 29094a3e9fdbSToby Isaac IS cellIS; 29104a3e9fdbSToby Isaac PetscInt depth; 2911a925c78cSMatthew G. Knepley PetscErrorCode ierr; 2912a925c78cSMatthew G. Knepley 2913a925c78cSMatthew G. Knepley PetscFunctionBegin; 2914a925c78cSMatthew G. Knepley ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 29154a3e9fdbSToby Isaac ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 2916aeadca18SToby Isaac ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr); 29174a3e9fdbSToby Isaac if (!cellIS) { 29184a3e9fdbSToby Isaac ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr); 29194a3e9fdbSToby Isaac } 29204a3e9fdbSToby Isaac ierr = DMPlexComputeJacobianAction_Internal(plex, cellIS, 0.0, 0.0, X, NULL, Y, Z, user);CHKERRQ(ierr); 2921c4e6da2cSBarry Smith ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 2922a925c78cSMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 2923a925c78cSMatthew G. Knepley PetscFunctionReturn(0); 2924a925c78cSMatthew G. Knepley } 2925a925c78cSMatthew G. Knepley 29269f520fc2SToby Isaac /*@ 29279f520fc2SToby Isaac DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian. 29289f520fc2SToby Isaac 29299f520fc2SToby Isaac Input Parameters: 29309f520fc2SToby Isaac + dm - The DM object 2931dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary()) 29329f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual()) 29339f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian()) 29341a244344SSatish Balay 29351a244344SSatish Balay Level: developer 29369f520fc2SToby Isaac @*/ 29379f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx) 29389f520fc2SToby Isaac { 29399f520fc2SToby Isaac PetscErrorCode ierr; 29409f520fc2SToby Isaac 29419f520fc2SToby Isaac PetscFunctionBegin; 29429f520fc2SToby Isaac ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr); 29439f520fc2SToby Isaac ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr); 29449f520fc2SToby Isaac ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr); 29459f520fc2SToby Isaac PetscFunctionReturn(0); 29469f520fc2SToby Isaac } 29479f520fc2SToby Isaac 29480163fd50SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions_Internal(SNES snes, DM dm, Vec u, Vec sol, PetscErrorCode (**exactFuncs)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx), void **ctxs) 29491878804aSMatthew G. Knepley { 2950282e7bb4SMatthew G. Knepley PetscDS prob; 29511878804aSMatthew G. Knepley Mat J, M; 29521878804aSMatthew G. Knepley Vec r, b; 29531878804aSMatthew G. Knepley MatNullSpace nullSpace; 29541878804aSMatthew G. Knepley PetscReal *error, res = 0.0; 29551878804aSMatthew G. Knepley PetscInt numFields; 2956282e7bb4SMatthew G. Knepley PetscBool hasJac, hasPrec; 29571878804aSMatthew G. Knepley PetscErrorCode ierr; 29581878804aSMatthew G. Knepley 29591878804aSMatthew G. Knepley PetscFunctionBegin; 29601878804aSMatthew G. Knepley ierr = VecDuplicate(u, &r);CHKERRQ(ierr); 29611878804aSMatthew G. Knepley ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr); 29621878804aSMatthew G. Knepley /* TODO Null space for J */ 29631878804aSMatthew G. Knepley /* Check discretization error */ 29641878804aSMatthew G. Knepley ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 29651878804aSMatthew G. Knepley ierr = PetscMalloc1(PetscMax(1, numFields), &error);CHKERRQ(ierr); 29661878804aSMatthew G. Knepley if (numFields > 1) { 29671878804aSMatthew G. Knepley PetscInt f; 29681878804aSMatthew G. Knepley 29691189c1efSToby Isaac ierr = DMComputeL2FieldDiff(dm, 0.0, exactFuncs, ctxs, u, error);CHKERRQ(ierr); 29701878804aSMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: [");CHKERRQ(ierr); 29711878804aSMatthew G. Knepley for (f = 0; f < numFields; ++f) { 29721878804aSMatthew G. Knepley if (f) {ierr = PetscPrintf(PETSC_COMM_WORLD, ", ");CHKERRQ(ierr);} 2973e5b268a4SToby Isaac if (error[f] >= 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "%g", (double)error[f]);CHKERRQ(ierr);} 29741878804aSMatthew G. Knepley else {ierr = PetscPrintf(PETSC_COMM_WORLD, "< 1.0e-11");CHKERRQ(ierr);} 29751878804aSMatthew G. Knepley } 29761878804aSMatthew G. Knepley ierr = PetscPrintf(PETSC_COMM_WORLD, "]\n");CHKERRQ(ierr); 29771878804aSMatthew G. Knepley } else { 29780709b2feSToby Isaac ierr = DMComputeL2Diff(dm, 0.0, exactFuncs, ctxs, u, &error[0]);CHKERRQ(ierr); 2979e5b268a4SToby Isaac if (error[0] >= 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", (double)error[0]);CHKERRQ(ierr);} 29801878804aSMatthew G. Knepley else {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);} 29811878804aSMatthew G. Knepley } 29821878804aSMatthew G. Knepley ierr = PetscFree(error);CHKERRQ(ierr); 29831878804aSMatthew G. Knepley /* Check residual */ 29841878804aSMatthew G. Knepley ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); 29851878804aSMatthew G. Knepley ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); 2986e5b268a4SToby Isaac ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr); 29871878804aSMatthew G. Knepley ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); 29881878804aSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr); 2989685405a1SBarry Smith ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr); 2990685405a1SBarry Smith ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr); 29911878804aSMatthew G. Knepley /* Check Jacobian */ 2992282e7bb4SMatthew G. Knepley ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 2993282e7bb4SMatthew G. Knepley ierr = PetscDSHasJacobian(prob, &hasJac);CHKERRQ(ierr); 2994282e7bb4SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr); 2995282e7bb4SMatthew G. Knepley if (hasJac && hasPrec) { 2996282e7bb4SMatthew G. Knepley ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr); 2997282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr); 2998282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr); 2999282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr); 3000282e7bb4SMatthew G. Knepley ierr = MatDestroy(&M);CHKERRQ(ierr); 3001282e7bb4SMatthew G. Knepley } else { 3002282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr); 3003282e7bb4SMatthew G. Knepley } 3004282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr); 3005282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr); 30061878804aSMatthew G. Knepley ierr = MatGetNullSpace(J, &nullSpace);CHKERRQ(ierr); 30071878804aSMatthew G. Knepley if (nullSpace) { 30081878804aSMatthew G. Knepley PetscBool isNull; 30091878804aSMatthew G. Knepley ierr = MatNullSpaceTest(nullSpace, J, &isNull);CHKERRQ(ierr); 30101878804aSMatthew G. Knepley if (!isNull) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid."); 30111878804aSMatthew G. Knepley } 30121878804aSMatthew G. Knepley ierr = VecDuplicate(u, &b);CHKERRQ(ierr); 30131878804aSMatthew G. Knepley ierr = VecSet(r, 0.0);CHKERRQ(ierr); 30141878804aSMatthew G. Knepley ierr = SNESComputeFunction(snes, r, b);CHKERRQ(ierr); 3015282e7bb4SMatthew G. Knepley ierr = MatMult(J, u, r);CHKERRQ(ierr); 30161878804aSMatthew G. Knepley ierr = VecAXPY(r, 1.0, b);CHKERRQ(ierr); 30171878804aSMatthew G. Knepley ierr = VecDestroy(&b);CHKERRQ(ierr); 30181878804aSMatthew G. Knepley ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); 3019e5b268a4SToby Isaac ierr = PetscPrintf(PETSC_COMM_WORLD, "Linear L_2 Residual: %g\n", (double)res);CHKERRQ(ierr); 30201878804aSMatthew G. Knepley ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); 30211878804aSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) r, "Au - b = Au + F(0)");CHKERRQ(ierr); 3022685405a1SBarry Smith ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"linear_res_");CHKERRQ(ierr); 3023685405a1SBarry Smith ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr); 30241878804aSMatthew G. Knepley ierr = VecDestroy(&r);CHKERRQ(ierr); 30251878804aSMatthew G. Knepley ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 30261878804aSMatthew G. Knepley ierr = MatDestroy(&J);CHKERRQ(ierr); 30271878804aSMatthew G. Knepley PetscFunctionReturn(0); 30281878804aSMatthew G. Knepley } 30291878804aSMatthew G. Knepley 30300163fd50SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u, PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx), void **ctxs) 30311878804aSMatthew G. Knepley { 30321878804aSMatthew G. Knepley DM dm; 30331878804aSMatthew G. Knepley Vec sol; 30341878804aSMatthew G. Knepley PetscBool check; 30351878804aSMatthew G. Knepley PetscErrorCode ierr; 30361878804aSMatthew G. Knepley 30371878804aSMatthew G. Knepley PetscFunctionBegin; 3038c5929fdfSBarry Smith ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr); 30391878804aSMatthew G. Knepley if (!check) PetscFunctionReturn(0); 30401878804aSMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 30411878804aSMatthew G. Knepley ierr = VecDuplicate(u, &sol);CHKERRQ(ierr); 30421878804aSMatthew G. Knepley ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr); 30431878804aSMatthew G. Knepley ierr = DMSNESCheckFromOptions_Internal(snes, dm, u, sol, exactFuncs, ctxs);CHKERRQ(ierr); 30441878804aSMatthew G. Knepley ierr = VecDestroy(&sol);CHKERRQ(ierr); 3045552f7358SJed Brown PetscFunctionReturn(0); 3046552f7358SJed Brown } 3047