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 8649ef022SMatthew Knepley static void pressure_Private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 9649ef022SMatthew Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 10649ef022SMatthew Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 11649ef022SMatthew Knepley PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar p[]) 12649ef022SMatthew Knepley { 13649ef022SMatthew Knepley p[0] = u[uOff[1]]; 14649ef022SMatthew Knepley } 15649ef022SMatthew Knepley 16649ef022SMatthew Knepley /* 17649ef022SMatthew Knepley SNESCorrectDiscretePressure_Private - Add a vector in the nullspace to make the continuum integral of the pressure field equal to zero. This is normally used only to evaluate convergence rates for the pressure accurately. 18649ef022SMatthew Knepley 19649ef022SMatthew Knepley Collective on SNES 20649ef022SMatthew Knepley 21649ef022SMatthew Knepley Input Parameters: 22649ef022SMatthew Knepley + snes - The SNES 23649ef022SMatthew Knepley . pfield - The field number for pressure 24649ef022SMatthew Knepley . nullspace - The pressure nullspace 25649ef022SMatthew Knepley . u - The solution vector 26649ef022SMatthew Knepley - ctx - An optional user context 27649ef022SMatthew Knepley 28649ef022SMatthew Knepley Output Parameter: 29649ef022SMatthew Knepley . u - The solution with a continuum pressure integral of zero 30649ef022SMatthew Knepley 31649ef022SMatthew Knepley Notes: 32649ef022SMatthew Knepley If int(u) = a and int(n) = b, then int(u - a/b n) = a - a/b b = 0. We assume that the nullspace is a single vector given explicitly. 33649ef022SMatthew Knepley 34649ef022SMatthew Knepley Level: developer 35649ef022SMatthew Knepley 36649ef022SMatthew Knepley .seealso: SNESConvergedCorrectPressure() 37649ef022SMatthew Knepley */ 38649ef022SMatthew Knepley static PetscErrorCode SNESCorrectDiscretePressure_Private(SNES snes, PetscInt pfield, MatNullSpace nullspace, Vec u, void *ctx) 39649ef022SMatthew Knepley { 40649ef022SMatthew Knepley DM dm; 41649ef022SMatthew Knepley PetscDS ds; 42649ef022SMatthew Knepley const Vec *nullvecs; 43649ef022SMatthew Knepley PetscScalar pintd, *intc, *intn; 44649ef022SMatthew Knepley MPI_Comm comm; 45649ef022SMatthew Knepley PetscInt Nf, Nv; 46649ef022SMatthew Knepley PetscErrorCode ierr; 47649ef022SMatthew Knepley 48649ef022SMatthew Knepley PetscFunctionBegin; 49649ef022SMatthew Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 50649ef022SMatthew Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 51649ef022SMatthew Knepley if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a SNES DM"); 52649ef022SMatthew Knepley if (!nullspace) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a Jacobian nullspace"); 53649ef022SMatthew Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 54649ef022SMatthew Knepley ierr = PetscDSSetObjective(ds, pfield, pressure_Private);CHKERRQ(ierr); 55649ef022SMatthew Knepley ierr = MatNullSpaceGetVecs(nullspace, NULL, &Nv, &nullvecs);CHKERRQ(ierr); 56649ef022SMatthew Knepley if (Nv != 1) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Can only handle a single null vector for pressure, not %D", Nv); 57649ef022SMatthew Knepley ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr); 58649ef022SMatthew Knepley if (PetscAbsScalar(pintd) > PETSC_SMALL) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd)); 59649ef022SMatthew Knepley ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 60649ef022SMatthew Knepley ierr = PetscMalloc2(Nf, &intc, Nf, &intn);CHKERRQ(ierr); 61649ef022SMatthew Knepley ierr = DMPlexComputeIntegralFEM(dm, nullvecs[0], intn, ctx);CHKERRQ(ierr); 62649ef022SMatthew Knepley ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr); 63649ef022SMatthew Knepley ierr = VecAXPY(u, -intc[pfield]/intn[pfield], nullvecs[0]);CHKERRQ(ierr); 64649ef022SMatthew Knepley #if defined (PETSC_USE_DEBUG) 65649ef022SMatthew Knepley ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr); 66649ef022SMatthew Knepley if (PetscAbsScalar(intc[pfield]) > PETSC_SMALL) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Continuum integral of pressure after correction: %g\n", (double) PetscRealPart(intc[pfield])); 67649ef022SMatthew Knepley #endif 68649ef022SMatthew Knepley ierr = PetscFree2(intc, intn);CHKERRQ(ierr); 69649ef022SMatthew Knepley PetscFunctionReturn(0); 70649ef022SMatthew Knepley } 71649ef022SMatthew Knepley 72649ef022SMatthew Knepley /*@C 73649ef022SMatthew Knepley SNESConvergedCorrectPressure - Convergence test that adds a vector in the nullspace to make the continuum integral of the pressure field equal to zero. This is normally used only to evaluate convergence rates for the pressure accurately. The convergence test itself just mimics SNESConvergedDefault(). 74649ef022SMatthew Knepley 75649ef022SMatthew Knepley Logically Collective on SNES 76649ef022SMatthew Knepley 77649ef022SMatthew Knepley Input Parameters: 78649ef022SMatthew Knepley + snes - the SNES context 79649ef022SMatthew Knepley . it - the iteration (0 indicates before any Newton steps) 80649ef022SMatthew Knepley . xnorm - 2-norm of current iterate 81649ef022SMatthew Knepley . snorm - 2-norm of current step 82649ef022SMatthew Knepley . fnorm - 2-norm of function at current iterate 83649ef022SMatthew Knepley - ctx - Optional user context 84649ef022SMatthew Knepley 85649ef022SMatthew Knepley Output Parameter: 86649ef022SMatthew Knepley . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 87649ef022SMatthew Knepley 88649ef022SMatthew Knepley Notes: 89649ef022SMatthew Knepley In order to use this monitor, you must setup several PETSc structures. First fields must be added to the DM, and a PetscDS must be created with discretizations of those fields. We currently assume that the pressure field has index 1. The pressure field must have a nullspace, likely created using the DMSetNullSpaceConstructor() interface. Last we must be able to integrate the pressure over the domain, so the DM attached to the SNES must be a Plex at this time. 90649ef022SMatthew Knepley 91649ef022SMatthew Knepley Level: advanced 92649ef022SMatthew Knepley 93649ef022SMatthew Knepley .seealso: SNESConvergedDefault(), SNESSetConvergenceTest(), DMSetNullSpaceConstructor() 94649ef022SMatthew Knepley @*/ 95649ef022SMatthew Knepley PetscErrorCode SNESConvergedCorrectPressure(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *ctx) 96649ef022SMatthew Knepley { 97649ef022SMatthew Knepley PetscBool monitorIntegral = PETSC_FALSE; 98649ef022SMatthew Knepley PetscErrorCode ierr; 99649ef022SMatthew Knepley 100649ef022SMatthew Knepley PetscFunctionBegin; 101649ef022SMatthew Knepley ierr = SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx);CHKERRQ(ierr); 102649ef022SMatthew Knepley if (monitorIntegral) { 103649ef022SMatthew Knepley Mat J; 104649ef022SMatthew Knepley Vec u; 105649ef022SMatthew Knepley MatNullSpace nullspace; 106649ef022SMatthew Knepley const Vec *nullvecs; 107649ef022SMatthew Knepley PetscScalar pintd; 108649ef022SMatthew Knepley 109649ef022SMatthew Knepley ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); 110649ef022SMatthew Knepley ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr); 111649ef022SMatthew Knepley ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr); 112649ef022SMatthew Knepley ierr = MatNullSpaceGetVecs(nullspace, NULL, NULL, &nullvecs);CHKERRQ(ierr); 113649ef022SMatthew Knepley ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr); 114649ef022SMatthew Knepley ierr = PetscInfo1(snes, "SNES: Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd));CHKERRQ(ierr); 115649ef022SMatthew Knepley } 116649ef022SMatthew Knepley if (*reason > 0) { 117649ef022SMatthew Knepley Mat J; 118649ef022SMatthew Knepley Vec u; 119649ef022SMatthew Knepley MatNullSpace nullspace; 120649ef022SMatthew Knepley PetscInt pfield = 1; 121649ef022SMatthew Knepley 122649ef022SMatthew Knepley ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); 123649ef022SMatthew Knepley ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr); 124649ef022SMatthew Knepley ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr); 125649ef022SMatthew Knepley ierr = SNESCorrectDiscretePressure_Private(snes, pfield, nullspace, u, ctx);CHKERRQ(ierr); 126649ef022SMatthew Knepley } 127649ef022SMatthew Knepley PetscFunctionReturn(0); 128649ef022SMatthew Knepley } 129649ef022SMatthew Knepley 13024cdb843SMatthew G. Knepley /************************** Interpolation *******************************/ 13124cdb843SMatthew G. Knepley 1326da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy) 1336da023fcSToby Isaac { 1346da023fcSToby Isaac PetscBool isPlex; 1356da023fcSToby Isaac PetscErrorCode ierr; 1366da023fcSToby Isaac 1376da023fcSToby Isaac PetscFunctionBegin; 1386da023fcSToby Isaac ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr); 1396da023fcSToby Isaac if (isPlex) { 1406da023fcSToby Isaac *plex = dm; 1416da023fcSToby Isaac ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 142f7148743SMatthew G. Knepley } else { 143f7148743SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex);CHKERRQ(ierr); 144f7148743SMatthew G. Knepley if (!*plex) { 1456da023fcSToby Isaac ierr = DMConvert(dm,DMPLEX,plex);CHKERRQ(ierr); 146f7148743SMatthew G. Knepley ierr = PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex);CHKERRQ(ierr); 1476da023fcSToby Isaac if (copy) { 1486da023fcSToby Isaac ierr = DMCopyDMSNES(dm, *plex);CHKERRQ(ierr); 1499a2a23afSMatthew G. Knepley ierr = DMCopyAuxiliaryVec(dm, *plex);CHKERRQ(ierr); 1506da023fcSToby Isaac } 151f7148743SMatthew G. Knepley } else { 152f7148743SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) *plex);CHKERRQ(ierr); 153f7148743SMatthew G. Knepley } 1546da023fcSToby Isaac } 1556da023fcSToby Isaac PetscFunctionReturn(0); 1566da023fcSToby Isaac } 1576da023fcSToby Isaac 1584267b1a3SMatthew G. Knepley /*@C 1594267b1a3SMatthew G. Knepley DMInterpolationCreate - Creates a DMInterpolationInfo context 1604267b1a3SMatthew G. Knepley 161d083f849SBarry Smith Collective 1624267b1a3SMatthew G. Knepley 1634267b1a3SMatthew G. Knepley Input Parameter: 1644267b1a3SMatthew G. Knepley . comm - the communicator 1654267b1a3SMatthew G. Knepley 1664267b1a3SMatthew G. Knepley Output Parameter: 1674267b1a3SMatthew G. Knepley . ctx - the context 1684267b1a3SMatthew G. Knepley 1694267b1a3SMatthew G. Knepley Level: beginner 1704267b1a3SMatthew G. Knepley 1714267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationDestroy() 1724267b1a3SMatthew G. Knepley @*/ 1730adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx) 1740adebc6cSBarry Smith { 175552f7358SJed Brown PetscErrorCode ierr; 176552f7358SJed Brown 177552f7358SJed Brown PetscFunctionBegin; 178552f7358SJed Brown PetscValidPointer(ctx, 2); 17995dccacaSBarry Smith ierr = PetscNew(ctx);CHKERRQ(ierr); 1801aa26658SKarl Rupp 181552f7358SJed Brown (*ctx)->comm = comm; 182552f7358SJed Brown (*ctx)->dim = -1; 183552f7358SJed Brown (*ctx)->nInput = 0; 1840298fd71SBarry Smith (*ctx)->points = NULL; 1850298fd71SBarry Smith (*ctx)->cells = NULL; 186552f7358SJed Brown (*ctx)->n = -1; 1870298fd71SBarry Smith (*ctx)->coords = NULL; 188552f7358SJed Brown PetscFunctionReturn(0); 189552f7358SJed Brown } 190552f7358SJed Brown 1914267b1a3SMatthew G. Knepley /*@C 1924267b1a3SMatthew G. Knepley DMInterpolationSetDim - Sets the spatial dimension for the interpolation context 1934267b1a3SMatthew G. Knepley 1944267b1a3SMatthew G. Knepley Not collective 1954267b1a3SMatthew G. Knepley 1964267b1a3SMatthew G. Knepley Input Parameters: 1974267b1a3SMatthew G. Knepley + ctx - the context 1984267b1a3SMatthew G. Knepley - dim - the spatial dimension 1994267b1a3SMatthew G. Knepley 2004267b1a3SMatthew G. Knepley Level: intermediate 2014267b1a3SMatthew G. Knepley 2024267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2034267b1a3SMatthew G. Knepley @*/ 2040adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim) 2050adebc6cSBarry Smith { 206552f7358SJed Brown PetscFunctionBegin; 207ff1e0c32SBarry Smith if ((dim < 1) || (dim > 3)) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %D", dim); 208552f7358SJed Brown ctx->dim = dim; 209552f7358SJed Brown PetscFunctionReturn(0); 210552f7358SJed Brown } 211552f7358SJed Brown 2124267b1a3SMatthew G. Knepley /*@C 2134267b1a3SMatthew G. Knepley DMInterpolationGetDim - Gets the spatial dimension for the interpolation context 2144267b1a3SMatthew G. Knepley 2154267b1a3SMatthew G. Knepley Not collective 2164267b1a3SMatthew G. Knepley 2174267b1a3SMatthew G. Knepley Input Parameter: 2184267b1a3SMatthew G. Knepley . ctx - the context 2194267b1a3SMatthew G. Knepley 2204267b1a3SMatthew G. Knepley Output Parameter: 2214267b1a3SMatthew G. Knepley . dim - the spatial dimension 2224267b1a3SMatthew G. Knepley 2234267b1a3SMatthew G. Knepley Level: intermediate 2244267b1a3SMatthew G. Knepley 2254267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2264267b1a3SMatthew G. Knepley @*/ 2270adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim) 2280adebc6cSBarry Smith { 229552f7358SJed Brown PetscFunctionBegin; 230552f7358SJed Brown PetscValidIntPointer(dim, 2); 231552f7358SJed Brown *dim = ctx->dim; 232552f7358SJed Brown PetscFunctionReturn(0); 233552f7358SJed Brown } 234552f7358SJed Brown 2354267b1a3SMatthew G. Knepley /*@C 2364267b1a3SMatthew G. Knepley DMInterpolationSetDof - Sets the number of fields interpolated at a point for the interpolation context 2374267b1a3SMatthew G. Knepley 2384267b1a3SMatthew G. Knepley Not collective 2394267b1a3SMatthew G. Knepley 2404267b1a3SMatthew G. Knepley Input Parameters: 2414267b1a3SMatthew G. Knepley + ctx - the context 2424267b1a3SMatthew G. Knepley - dof - the number of fields 2434267b1a3SMatthew G. Knepley 2444267b1a3SMatthew G. Knepley Level: intermediate 2454267b1a3SMatthew G. Knepley 2464267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2474267b1a3SMatthew G. Knepley @*/ 2480adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof) 2490adebc6cSBarry Smith { 250552f7358SJed Brown PetscFunctionBegin; 251ff1e0c32SBarry Smith if (dof < 1) SETERRQ1(ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %D", dof); 252552f7358SJed Brown ctx->dof = dof; 253552f7358SJed Brown PetscFunctionReturn(0); 254552f7358SJed Brown } 255552f7358SJed Brown 2564267b1a3SMatthew G. Knepley /*@C 2574267b1a3SMatthew G. Knepley DMInterpolationGetDof - Gets the number of fields interpolated at a point for the interpolation context 2584267b1a3SMatthew G. Knepley 2594267b1a3SMatthew G. Knepley Not collective 2604267b1a3SMatthew G. Knepley 2614267b1a3SMatthew G. Knepley Input Parameter: 2624267b1a3SMatthew G. Knepley . ctx - the context 2634267b1a3SMatthew G. Knepley 2644267b1a3SMatthew G. Knepley Output Parameter: 2654267b1a3SMatthew G. Knepley . dof - the number of fields 2664267b1a3SMatthew G. Knepley 2674267b1a3SMatthew G. Knepley Level: intermediate 2684267b1a3SMatthew G. Knepley 2694267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2704267b1a3SMatthew G. Knepley @*/ 2710adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof) 2720adebc6cSBarry Smith { 273552f7358SJed Brown PetscFunctionBegin; 274552f7358SJed Brown PetscValidIntPointer(dof, 2); 275552f7358SJed Brown *dof = ctx->dof; 276552f7358SJed Brown PetscFunctionReturn(0); 277552f7358SJed Brown } 278552f7358SJed Brown 2794267b1a3SMatthew G. Knepley /*@C 2804267b1a3SMatthew G. Knepley DMInterpolationAddPoints - Add points at which we will interpolate the fields 2814267b1a3SMatthew G. Knepley 2824267b1a3SMatthew G. Knepley Not collective 2834267b1a3SMatthew G. Knepley 2844267b1a3SMatthew G. Knepley Input Parameters: 2854267b1a3SMatthew G. Knepley + ctx - the context 2864267b1a3SMatthew G. Knepley . n - the number of points 2874267b1a3SMatthew G. Knepley - points - the coordinates for each point, an array of size n * dim 2884267b1a3SMatthew G. Knepley 2894267b1a3SMatthew G. Knepley Note: The coordinate information is copied. 2904267b1a3SMatthew G. Knepley 2914267b1a3SMatthew G. Knepley Level: intermediate 2924267b1a3SMatthew G. Knepley 2934267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationCreate() 2944267b1a3SMatthew G. Knepley @*/ 2950adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[]) 2960adebc6cSBarry Smith { 297552f7358SJed Brown PetscErrorCode ierr; 298552f7358SJed Brown 299552f7358SJed Brown PetscFunctionBegin; 3000adebc6cSBarry Smith if (ctx->dim < 0) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 3010adebc6cSBarry Smith if (ctx->points) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet"); 302552f7358SJed Brown ctx->nInput = n; 3031aa26658SKarl Rupp 304785e854fSJed Brown ierr = PetscMalloc1(n*ctx->dim, &ctx->points);CHKERRQ(ierr); 305580bdb30SBarry Smith ierr = PetscArraycpy(ctx->points, points, n*ctx->dim);CHKERRQ(ierr); 306552f7358SJed Brown PetscFunctionReturn(0); 307552f7358SJed Brown } 308552f7358SJed Brown 3094267b1a3SMatthew G. Knepley /*@C 31052aa1562SMatthew G. Knepley DMInterpolationSetUp - Compute spatial indices for point location during interpolation 3114267b1a3SMatthew G. Knepley 3124267b1a3SMatthew G. Knepley Collective on ctx 3134267b1a3SMatthew G. Knepley 3144267b1a3SMatthew G. Knepley Input Parameters: 3154267b1a3SMatthew G. Knepley + ctx - the context 3164267b1a3SMatthew G. Knepley . dm - the DM for the function space used for interpolation 31752aa1562SMatthew G. Knepley . redundantPoints - If PETSC_TRUE, all processes are passing in the same array of points. Otherwise, points need to be communicated among processes. 3187deeda50SSatish Balay - ignoreOutsideDomain - If PETSC_TRUE, ignore points outside the domain, otherwise return an error 3194267b1a3SMatthew G. Knepley 3204267b1a3SMatthew G. Knepley Level: intermediate 3214267b1a3SMatthew G. Knepley 3224267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 3234267b1a3SMatthew G. Knepley @*/ 32452aa1562SMatthew G. Knepley PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints, PetscBool ignoreOutsideDomain) 3250adebc6cSBarry Smith { 326552f7358SJed Brown MPI_Comm comm = ctx->comm; 327552f7358SJed Brown PetscScalar *a; 328552f7358SJed Brown PetscInt p, q, i; 329552f7358SJed Brown PetscMPIInt rank, size; 330552f7358SJed Brown PetscErrorCode ierr; 331552f7358SJed Brown Vec pointVec; 3323a93e3b7SToby Isaac PetscSF cellSF; 333552f7358SJed Brown PetscLayout layout; 334552f7358SJed Brown PetscReal *globalPoints; 335cb313848SJed Brown PetscScalar *globalPointsScalar; 336552f7358SJed Brown const PetscInt *ranges; 337552f7358SJed Brown PetscMPIInt *counts, *displs; 3383a93e3b7SToby Isaac const PetscSFNode *foundCells; 3393a93e3b7SToby Isaac const PetscInt *foundPoints; 340552f7358SJed Brown PetscMPIInt *foundProcs, *globalProcs; 3413a93e3b7SToby Isaac PetscInt n, N, numFound; 342552f7358SJed Brown 34319436ca2SJed Brown PetscFunctionBegin; 34419436ca2SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 345ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 346ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 3470adebc6cSBarry Smith if (ctx->dim < 0) SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 34819436ca2SJed Brown /* Locate points */ 34919436ca2SJed Brown n = ctx->nInput; 350552f7358SJed Brown if (!redundantPoints) { 351552f7358SJed Brown ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 352552f7358SJed Brown ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 353552f7358SJed Brown ierr = PetscLayoutSetLocalSize(layout, n);CHKERRQ(ierr); 354552f7358SJed Brown ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 355552f7358SJed Brown ierr = PetscLayoutGetSize(layout, &N);CHKERRQ(ierr); 356552f7358SJed Brown /* Communicate all points to all processes */ 357dcca6d9dSJed Brown ierr = PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs);CHKERRQ(ierr); 358552f7358SJed Brown ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 359552f7358SJed Brown for (p = 0; p < size; ++p) { 360552f7358SJed Brown counts[p] = (ranges[p+1] - ranges[p])*ctx->dim; 361552f7358SJed Brown displs[p] = ranges[p]*ctx->dim; 362552f7358SJed Brown } 363ffc4695bSBarry Smith ierr = MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm);CHKERRMPI(ierr); 364552f7358SJed Brown } else { 365552f7358SJed Brown N = n; 366552f7358SJed Brown globalPoints = ctx->points; 36738ea73c8SJed Brown counts = displs = NULL; 36838ea73c8SJed Brown layout = NULL; 369552f7358SJed Brown } 370552f7358SJed Brown #if 0 371dcca6d9dSJed Brown ierr = PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs);CHKERRQ(ierr); 37219436ca2SJed Brown /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */ 373552f7358SJed Brown #else 374cb313848SJed Brown #if defined(PETSC_USE_COMPLEX) 37546b3086cSToby Isaac ierr = PetscMalloc1(N*ctx->dim,&globalPointsScalar);CHKERRQ(ierr); 37646b3086cSToby Isaac for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i]; 377cb313848SJed Brown #else 378cb313848SJed Brown globalPointsScalar = globalPoints; 379cb313848SJed Brown #endif 38004706141SMatthew G Knepley ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec);CHKERRQ(ierr); 381dcca6d9dSJed Brown ierr = PetscMalloc2(N,&foundProcs,N,&globalProcs);CHKERRQ(ierr); 3827b5f2079SMatthew G. Knepley for (p = 0; p < N; ++p) {foundProcs[p] = size;} 3833a93e3b7SToby Isaac cellSF = NULL; 3842d1fa6caSMatthew G. Knepley ierr = DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF);CHKERRQ(ierr); 3853a93e3b7SToby Isaac ierr = PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells);CHKERRQ(ierr); 386552f7358SJed Brown #endif 3873a93e3b7SToby Isaac for (p = 0; p < numFound; ++p) { 3883a93e3b7SToby Isaac if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank; 389552f7358SJed Brown } 390552f7358SJed Brown /* Let the lowest rank process own each point */ 391*820f2d46SBarry Smith ierr = MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm);CHKERRMPI(ierr); 392552f7358SJed Brown ctx->n = 0; 393552f7358SJed Brown for (p = 0; p < N; ++p) { 39452aa1562SMatthew G. Knepley if (globalProcs[p] == size) { 39552aa1562SMatthew G. Knepley if (!ignoreOutsideDomain) 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)); 39652aa1562SMatthew G. Knepley else if (!rank) ++ctx->n; 39752aa1562SMatthew G. Knepley } else if (globalProcs[p] == rank) ++ctx->n; 398552f7358SJed Brown } 399552f7358SJed Brown /* Create coordinates vector and array of owned cells */ 400785e854fSJed Brown ierr = PetscMalloc1(ctx->n, &ctx->cells);CHKERRQ(ierr); 401552f7358SJed Brown ierr = VecCreate(comm, &ctx->coords);CHKERRQ(ierr); 402552f7358SJed Brown ierr = VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE);CHKERRQ(ierr); 403552f7358SJed Brown ierr = VecSetBlockSize(ctx->coords, ctx->dim);CHKERRQ(ierr); 404c0dedaeaSBarry Smith ierr = VecSetType(ctx->coords,VECSTANDARD);CHKERRQ(ierr); 405552f7358SJed Brown ierr = VecGetArray(ctx->coords, &a);CHKERRQ(ierr); 406552f7358SJed Brown for (p = 0, q = 0, i = 0; p < N; ++p) { 407552f7358SJed Brown if (globalProcs[p] == rank) { 408552f7358SJed Brown PetscInt d; 409552f7358SJed Brown 4101aa26658SKarl Rupp for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d]; 411f317b747SMatthew G. Knepley ctx->cells[q] = foundCells[q].index; 412f317b747SMatthew G. Knepley ++q; 413552f7358SJed Brown } 41452aa1562SMatthew G. Knepley if (globalProcs[p] == size && !rank) { 41552aa1562SMatthew G. Knepley PetscInt d; 41652aa1562SMatthew G. Knepley 41752aa1562SMatthew G. Knepley for (d = 0; d < ctx->dim; ++d, ++i) a[i] = 0.; 41852aa1562SMatthew G. Knepley ctx->cells[q] = -1; 41952aa1562SMatthew G. Knepley ++q; 42052aa1562SMatthew G. Knepley } 421552f7358SJed Brown } 422552f7358SJed Brown ierr = VecRestoreArray(ctx->coords, &a);CHKERRQ(ierr); 423552f7358SJed Brown #if 0 424552f7358SJed Brown ierr = PetscFree3(foundCells,foundProcs,globalProcs);CHKERRQ(ierr); 425552f7358SJed Brown #else 426552f7358SJed Brown ierr = PetscFree2(foundProcs,globalProcs);CHKERRQ(ierr); 4273a93e3b7SToby Isaac ierr = PetscSFDestroy(&cellSF);CHKERRQ(ierr); 428552f7358SJed Brown ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 429552f7358SJed Brown #endif 430cb313848SJed Brown if ((void*)globalPointsScalar != (void*)globalPoints) {ierr = PetscFree(globalPointsScalar);CHKERRQ(ierr);} 431d343d804SMatthew G. Knepley if (!redundantPoints) {ierr = PetscFree3(globalPoints,counts,displs);CHKERRQ(ierr);} 432552f7358SJed Brown ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 433552f7358SJed Brown PetscFunctionReturn(0); 434552f7358SJed Brown } 435552f7358SJed Brown 4364267b1a3SMatthew G. Knepley /*@C 4374267b1a3SMatthew G. Knepley DMInterpolationGetCoordinates - Gets a Vec with the coordinates of each interpolation point 4384267b1a3SMatthew G. Knepley 4394267b1a3SMatthew G. Knepley Collective on ctx 4404267b1a3SMatthew G. Knepley 4414267b1a3SMatthew G. Knepley Input Parameter: 4424267b1a3SMatthew G. Knepley . ctx - the context 4434267b1a3SMatthew G. Knepley 4444267b1a3SMatthew G. Knepley Output Parameter: 4454267b1a3SMatthew G. Knepley . coordinates - the coordinates of interpolation points 4464267b1a3SMatthew G. Knepley 4474267b1a3SMatthew G. Knepley Note: The local vector entries correspond to interpolation points lying on this process, according to the associated DM. This is a borrowed vector that the user should not destroy. 4484267b1a3SMatthew G. Knepley 4494267b1a3SMatthew G. Knepley Level: intermediate 4504267b1a3SMatthew G. Knepley 4514267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 4524267b1a3SMatthew G. Knepley @*/ 4530adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates) 4540adebc6cSBarry Smith { 455552f7358SJed Brown PetscFunctionBegin; 456552f7358SJed Brown PetscValidPointer(coordinates, 2); 4570adebc6cSBarry Smith if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 458552f7358SJed Brown *coordinates = ctx->coords; 459552f7358SJed Brown PetscFunctionReturn(0); 460552f7358SJed Brown } 461552f7358SJed Brown 4624267b1a3SMatthew G. Knepley /*@C 4634267b1a3SMatthew G. Knepley DMInterpolationGetVector - Gets a Vec which can hold all the interpolated field values 4644267b1a3SMatthew G. Knepley 4654267b1a3SMatthew G. Knepley Collective on ctx 4664267b1a3SMatthew G. Knepley 4674267b1a3SMatthew G. Knepley Input Parameter: 4684267b1a3SMatthew G. Knepley . ctx - the context 4694267b1a3SMatthew G. Knepley 4704267b1a3SMatthew G. Knepley Output Parameter: 4714267b1a3SMatthew G. Knepley . v - a vector capable of holding the interpolated field values 4724267b1a3SMatthew G. Knepley 4734267b1a3SMatthew G. Knepley Note: This vector should be returned using DMInterpolationRestoreVector(). 4744267b1a3SMatthew G. Knepley 4754267b1a3SMatthew G. Knepley Level: intermediate 4764267b1a3SMatthew G. Knepley 4774267b1a3SMatthew G. Knepley .seealso: DMInterpolationRestoreVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 4784267b1a3SMatthew G. Knepley @*/ 4790adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v) 4800adebc6cSBarry Smith { 481552f7358SJed Brown PetscErrorCode ierr; 482552f7358SJed Brown 483552f7358SJed Brown PetscFunctionBegin; 484552f7358SJed Brown PetscValidPointer(v, 2); 4850adebc6cSBarry Smith if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 486552f7358SJed Brown ierr = VecCreate(ctx->comm, v);CHKERRQ(ierr); 487552f7358SJed Brown ierr = VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE);CHKERRQ(ierr); 488552f7358SJed Brown ierr = VecSetBlockSize(*v, ctx->dof);CHKERRQ(ierr); 489c0dedaeaSBarry Smith ierr = VecSetType(*v,VECSTANDARD);CHKERRQ(ierr); 490552f7358SJed Brown PetscFunctionReturn(0); 491552f7358SJed Brown } 492552f7358SJed Brown 4934267b1a3SMatthew G. Knepley /*@C 4944267b1a3SMatthew G. Knepley DMInterpolationRestoreVector - Returns a Vec which can hold all the interpolated field values 4954267b1a3SMatthew G. Knepley 4964267b1a3SMatthew G. Knepley Collective on ctx 4974267b1a3SMatthew G. Knepley 4984267b1a3SMatthew G. Knepley Input Parameters: 4994267b1a3SMatthew G. Knepley + ctx - the context 5004267b1a3SMatthew G. Knepley - v - a vector capable of holding the interpolated field values 5014267b1a3SMatthew G. Knepley 5024267b1a3SMatthew G. Knepley Level: intermediate 5034267b1a3SMatthew G. Knepley 5044267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 5054267b1a3SMatthew G. Knepley @*/ 5060adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v) 5070adebc6cSBarry Smith { 508552f7358SJed Brown PetscErrorCode ierr; 509552f7358SJed Brown 510552f7358SJed Brown PetscFunctionBegin; 511552f7358SJed Brown PetscValidPointer(v, 2); 5120adebc6cSBarry Smith if (!ctx->coords) SETERRQ(ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 513552f7358SJed Brown ierr = VecDestroy(v);CHKERRQ(ierr); 514552f7358SJed Brown PetscFunctionReturn(0); 515552f7358SJed Brown } 516552f7358SJed Brown 5177a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 518a6dfd86eSKarl Rupp { 519552f7358SJed Brown PetscReal *v0, *J, *invJ, detJ; 52056044e6dSMatthew G. Knepley const PetscScalar *coords; 52156044e6dSMatthew G. Knepley PetscScalar *a; 522552f7358SJed Brown PetscInt p; 523552f7358SJed Brown PetscErrorCode ierr; 524552f7358SJed Brown 525552f7358SJed Brown PetscFunctionBegin; 526dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 52756044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 528552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 529552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 530552f7358SJed Brown PetscInt c = ctx->cells[p]; 531a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 532552f7358SJed Brown PetscReal xi[4]; 533552f7358SJed Brown PetscInt d, f, comp; 534552f7358SJed Brown 5358e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 536ff1e0c32SBarry Smith if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 5370298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 5381aa26658SKarl Rupp for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 5391aa26658SKarl Rupp 540552f7358SJed Brown for (d = 0; d < ctx->dim; ++d) { 541552f7358SJed Brown xi[d] = 0.0; 5421aa26658SKarl 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]); 5431aa26658SKarl 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]; 544552f7358SJed Brown } 5450298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 546552f7358SJed Brown } 547552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 54856044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 549552f7358SJed Brown ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 550552f7358SJed Brown PetscFunctionReturn(0); 551552f7358SJed Brown } 552552f7358SJed Brown 5537a1931ceSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 5547a1931ceSMatthew G. Knepley { 5557a1931ceSMatthew G. Knepley PetscReal *v0, *J, *invJ, detJ; 55656044e6dSMatthew G. Knepley const PetscScalar *coords; 55756044e6dSMatthew G. Knepley PetscScalar *a; 5587a1931ceSMatthew G. Knepley PetscInt p; 5597a1931ceSMatthew G. Knepley PetscErrorCode ierr; 5607a1931ceSMatthew G. Knepley 5617a1931ceSMatthew G. Knepley PetscFunctionBegin; 562dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 56356044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 5647a1931ceSMatthew G. Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 5657a1931ceSMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 5667a1931ceSMatthew G. Knepley PetscInt c = ctx->cells[p]; 5677a1931ceSMatthew G. Knepley const PetscInt order[3] = {2, 1, 3}; 5682584bbe8SMatthew G. Knepley PetscScalar *x = NULL; 5697a1931ceSMatthew G. Knepley PetscReal xi[4]; 5707a1931ceSMatthew G. Knepley PetscInt d, f, comp; 5717a1931ceSMatthew G. Knepley 5728e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 573ff1e0c32SBarry Smith if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 5747a1931ceSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 5757a1931ceSMatthew G. Knepley for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 5767a1931ceSMatthew G. Knepley 5777a1931ceSMatthew G. Knepley for (d = 0; d < ctx->dim; ++d) { 5787a1931ceSMatthew G. Knepley xi[d] = 0.0; 5797a1931ceSMatthew 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]); 5807a1931ceSMatthew 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]; 5817a1931ceSMatthew G. Knepley } 5827a1931ceSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 5837a1931ceSMatthew G. Knepley } 5847a1931ceSMatthew G. Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 58556044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 5867a1931ceSMatthew G. Knepley ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 5877a1931ceSMatthew G. Knepley PetscFunctionReturn(0); 5887a1931ceSMatthew G. Knepley } 5897a1931ceSMatthew G. Knepley 5905820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 591552f7358SJed Brown { 592552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 593552f7358SJed Brown const PetscScalar x0 = vertices[0]; 594552f7358SJed Brown const PetscScalar y0 = vertices[1]; 595552f7358SJed Brown const PetscScalar x1 = vertices[2]; 596552f7358SJed Brown const PetscScalar y1 = vertices[3]; 597552f7358SJed Brown const PetscScalar x2 = vertices[4]; 598552f7358SJed Brown const PetscScalar y2 = vertices[5]; 599552f7358SJed Brown const PetscScalar x3 = vertices[6]; 600552f7358SJed Brown const PetscScalar y3 = vertices[7]; 601552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 602552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 603552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 604552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 605552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 606552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 60756044e6dSMatthew G. Knepley const PetscScalar *ref; 60856044e6dSMatthew G. Knepley PetscScalar *real; 609552f7358SJed Brown PetscErrorCode ierr; 610552f7358SJed Brown 611552f7358SJed Brown PetscFunctionBegin; 61256044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 613552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 614552f7358SJed Brown { 615552f7358SJed Brown const PetscScalar p0 = ref[0]; 616552f7358SJed Brown const PetscScalar p1 = ref[1]; 617552f7358SJed Brown 618552f7358SJed Brown real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1; 619552f7358SJed Brown real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1; 620552f7358SJed Brown } 621552f7358SJed Brown ierr = PetscLogFlops(28);CHKERRQ(ierr); 62256044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 623552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 624552f7358SJed Brown PetscFunctionReturn(0); 625552f7358SJed Brown } 626552f7358SJed Brown 627af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 628d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 629552f7358SJed Brown { 630552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 631552f7358SJed Brown const PetscScalar x0 = vertices[0]; 632552f7358SJed Brown const PetscScalar y0 = vertices[1]; 633552f7358SJed Brown const PetscScalar x1 = vertices[2]; 634552f7358SJed Brown const PetscScalar y1 = vertices[3]; 635552f7358SJed Brown const PetscScalar x2 = vertices[4]; 636552f7358SJed Brown const PetscScalar y2 = vertices[5]; 637552f7358SJed Brown const PetscScalar x3 = vertices[6]; 638552f7358SJed Brown const PetscScalar y3 = vertices[7]; 639552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 640552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 64156044e6dSMatthew G. Knepley const PetscScalar *ref; 642552f7358SJed Brown PetscErrorCode ierr; 643552f7358SJed Brown 644552f7358SJed Brown PetscFunctionBegin; 64556044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 646552f7358SJed Brown { 647552f7358SJed Brown const PetscScalar x = ref[0]; 648552f7358SJed Brown const PetscScalar y = ref[1]; 649552f7358SJed Brown const PetscInt rows[2] = {0, 1}; 650da80777bSKarl Rupp PetscScalar values[4]; 651da80777bSKarl Rupp 652da80777bSKarl Rupp values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5; 653da80777bSKarl Rupp values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5; 65494ab13aaSBarry Smith ierr = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr); 655552f7358SJed Brown } 656552f7358SJed Brown ierr = PetscLogFlops(30);CHKERRQ(ierr); 65756044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 65894ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 65994ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 660552f7358SJed Brown PetscFunctionReturn(0); 661552f7358SJed Brown } 662552f7358SJed Brown 663a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 664a6dfd86eSKarl Rupp { 665fafc0619SMatthew G Knepley DM dmCoord; 666de73a395SMatthew G. Knepley PetscFE fem = NULL; 667552f7358SJed Brown SNES snes; 668552f7358SJed Brown KSP ksp; 669552f7358SJed Brown PC pc; 670552f7358SJed Brown Vec coordsLocal, r, ref, real; 671552f7358SJed Brown Mat J; 672ef0bb6c7SMatthew G. Knepley PetscTabulation T; 67356044e6dSMatthew G. Knepley const PetscScalar *coords; 67456044e6dSMatthew G. Knepley PetscScalar *a; 675ef0bb6c7SMatthew G. Knepley PetscReal xir[2]; 676de73a395SMatthew G. Knepley PetscInt Nf, p; 6775509d985SMatthew G. Knepley const PetscInt dof = ctx->dof; 678552f7358SJed Brown PetscErrorCode ierr; 679552f7358SJed Brown 680552f7358SJed Brown PetscFunctionBegin; 681de73a395SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 68244a7f3ddSMatthew G. Knepley if (Nf) {ierr = DMGetField(dm, 0, NULL, (PetscObject *) &fem);CHKERRQ(ierr);} 683552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 684fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 685552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 686552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr); 687552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 688552f7358SJed Brown ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr); 689c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 690552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 691552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 692552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 693552f7358SJed Brown ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr); 694552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 695552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 6960298fd71SBarry Smith ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr); 6970298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr); 698552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 699552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 700552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 701552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 702552f7358SJed Brown 70356044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 704552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 705ef0bb6c7SMatthew G. Knepley ierr = PetscFECreateTabulation(fem, 1, 1, xir, 0, &T);CHKERRQ(ierr); 706552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 707a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 708552f7358SJed Brown PetscScalar *xi; 709552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 710552f7358SJed Brown 711552f7358SJed Brown /* Can make this do all points at once */ 7120298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 713ff1e0c32SBarry Smith if (4*2 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 4*2); 7140298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 7150298fd71SBarry Smith ierr = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 7160298fd71SBarry Smith ierr = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 717552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 718552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 719552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 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]); 7255509d985SMatthew G. Knepley if (4*dof != xSize) { 7265509d985SMatthew G. Knepley PetscInt d; 7271aa26658SKarl Rupp 7285509d985SMatthew G. Knepley xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0; 729ef0bb6c7SMatthew G. Knepley ierr = PetscFEComputeTabulation(fem, 1, xir, 0, T);CHKERRQ(ierr); 7305509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) { 7315509d985SMatthew G. Knepley a[p*dof+comp] = 0.0; 7325509d985SMatthew G. Knepley for (d = 0; d < xSize/dof; ++d) { 733ef0bb6c7SMatthew G. Knepley a[p*dof+comp] += x[d*dof+comp]*T->T[0][d*dof+comp]; 7345509d985SMatthew G. Knepley } 7355509d985SMatthew G. Knepley } 7365509d985SMatthew G. Knepley } else { 7375509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) 7385509d985SMatthew 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]; 7395509d985SMatthew G. Knepley } 740552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 7410298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 7420298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 743552f7358SJed Brown } 744ef0bb6c7SMatthew G. Knepley ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr); 745552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 74656044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 747552f7358SJed Brown 748552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 749552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 750552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 751552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 752552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 753552f7358SJed Brown PetscFunctionReturn(0); 754552f7358SJed Brown } 755552f7358SJed Brown 7565820edbdSMatthew G Knepley PETSC_STATIC_INLINE PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 757552f7358SJed Brown { 758552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 759552f7358SJed Brown const PetscScalar x0 = vertices[0]; 760552f7358SJed Brown const PetscScalar y0 = vertices[1]; 761552f7358SJed Brown const PetscScalar z0 = vertices[2]; 7627a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 7637a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 7647a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 765552f7358SJed Brown const PetscScalar x2 = vertices[6]; 766552f7358SJed Brown const PetscScalar y2 = vertices[7]; 767552f7358SJed Brown const PetscScalar z2 = vertices[8]; 7687a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 7697a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 7707a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 771552f7358SJed Brown const PetscScalar x4 = vertices[12]; 772552f7358SJed Brown const PetscScalar y4 = vertices[13]; 773552f7358SJed Brown const PetscScalar z4 = vertices[14]; 774552f7358SJed Brown const PetscScalar x5 = vertices[15]; 775552f7358SJed Brown const PetscScalar y5 = vertices[16]; 776552f7358SJed Brown const PetscScalar z5 = vertices[17]; 777552f7358SJed Brown const PetscScalar x6 = vertices[18]; 778552f7358SJed Brown const PetscScalar y6 = vertices[19]; 779552f7358SJed Brown const PetscScalar z6 = vertices[20]; 780552f7358SJed Brown const PetscScalar x7 = vertices[21]; 781552f7358SJed Brown const PetscScalar y7 = vertices[22]; 782552f7358SJed Brown const PetscScalar z7 = vertices[23]; 783552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 784552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 785552f7358SJed Brown const PetscScalar h_1 = z1 - z0; 786552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 787552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 788552f7358SJed Brown const PetscScalar h_3 = z3 - z0; 789552f7358SJed Brown const PetscScalar f_4 = x4 - x0; 790552f7358SJed Brown const PetscScalar g_4 = y4 - y0; 791552f7358SJed Brown const PetscScalar h_4 = z4 - z0; 792552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 793552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 794552f7358SJed Brown const PetscScalar h_01 = z2 - z1 - z3 + z0; 795552f7358SJed Brown const PetscScalar f_12 = x7 - x3 - x4 + x0; 796552f7358SJed Brown const PetscScalar g_12 = y7 - y3 - y4 + y0; 797552f7358SJed Brown const PetscScalar h_12 = z7 - z3 - z4 + z0; 798552f7358SJed Brown const PetscScalar f_02 = x5 - x1 - x4 + x0; 799552f7358SJed Brown const PetscScalar g_02 = y5 - y1 - y4 + y0; 800552f7358SJed Brown const PetscScalar h_02 = z5 - z1 - z4 + z0; 801552f7358SJed Brown const PetscScalar f_012 = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 802552f7358SJed Brown const PetscScalar g_012 = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 803552f7358SJed Brown const PetscScalar h_012 = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 80456044e6dSMatthew G. Knepley const PetscScalar *ref; 80556044e6dSMatthew G. Knepley PetscScalar *real; 806552f7358SJed Brown PetscErrorCode ierr; 807552f7358SJed Brown 808552f7358SJed Brown PetscFunctionBegin; 80956044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 810552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 811552f7358SJed Brown { 812552f7358SJed Brown const PetscScalar p0 = ref[0]; 813552f7358SJed Brown const PetscScalar p1 = ref[1]; 814552f7358SJed Brown const PetscScalar p2 = ref[2]; 815552f7358SJed Brown 816552f7358SJed 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; 817552f7358SJed 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; 818552f7358SJed 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; 819552f7358SJed Brown } 820552f7358SJed Brown ierr = PetscLogFlops(114);CHKERRQ(ierr); 82156044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 822552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 823552f7358SJed Brown PetscFunctionReturn(0); 824552f7358SJed Brown } 825552f7358SJed Brown 826d1e9a80fSBarry Smith PETSC_STATIC_INLINE PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 827552f7358SJed Brown { 828552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 829552f7358SJed Brown const PetscScalar x0 = vertices[0]; 830552f7358SJed Brown const PetscScalar y0 = vertices[1]; 831552f7358SJed Brown const PetscScalar z0 = vertices[2]; 8327a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 8337a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 8347a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 835552f7358SJed Brown const PetscScalar x2 = vertices[6]; 836552f7358SJed Brown const PetscScalar y2 = vertices[7]; 837552f7358SJed Brown const PetscScalar z2 = vertices[8]; 8387a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 8397a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 8407a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 841552f7358SJed Brown const PetscScalar x4 = vertices[12]; 842552f7358SJed Brown const PetscScalar y4 = vertices[13]; 843552f7358SJed Brown const PetscScalar z4 = vertices[14]; 844552f7358SJed Brown const PetscScalar x5 = vertices[15]; 845552f7358SJed Brown const PetscScalar y5 = vertices[16]; 846552f7358SJed Brown const PetscScalar z5 = vertices[17]; 847552f7358SJed Brown const PetscScalar x6 = vertices[18]; 848552f7358SJed Brown const PetscScalar y6 = vertices[19]; 849552f7358SJed Brown const PetscScalar z6 = vertices[20]; 850552f7358SJed Brown const PetscScalar x7 = vertices[21]; 851552f7358SJed Brown const PetscScalar y7 = vertices[22]; 852552f7358SJed Brown const PetscScalar z7 = vertices[23]; 853552f7358SJed Brown const PetscScalar f_xy = x2 - x1 - x3 + x0; 854552f7358SJed Brown const PetscScalar g_xy = y2 - y1 - y3 + y0; 855552f7358SJed Brown const PetscScalar h_xy = z2 - z1 - z3 + z0; 856552f7358SJed Brown const PetscScalar f_yz = x7 - x3 - x4 + x0; 857552f7358SJed Brown const PetscScalar g_yz = y7 - y3 - y4 + y0; 858552f7358SJed Brown const PetscScalar h_yz = z7 - z3 - z4 + z0; 859552f7358SJed Brown const PetscScalar f_xz = x5 - x1 - x4 + x0; 860552f7358SJed Brown const PetscScalar g_xz = y5 - y1 - y4 + y0; 861552f7358SJed Brown const PetscScalar h_xz = z5 - z1 - z4 + z0; 862552f7358SJed Brown const PetscScalar f_xyz = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 863552f7358SJed Brown const PetscScalar g_xyz = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 864552f7358SJed Brown const PetscScalar h_xyz = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 86556044e6dSMatthew G. Knepley const PetscScalar *ref; 866552f7358SJed Brown PetscErrorCode ierr; 867552f7358SJed Brown 868552f7358SJed Brown PetscFunctionBegin; 86956044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 870552f7358SJed Brown { 871552f7358SJed Brown const PetscScalar x = ref[0]; 872552f7358SJed Brown const PetscScalar y = ref[1]; 873552f7358SJed Brown const PetscScalar z = ref[2]; 874552f7358SJed Brown const PetscInt rows[3] = {0, 1, 2}; 875da80777bSKarl Rupp PetscScalar values[9]; 876da80777bSKarl Rupp 877da80777bSKarl Rupp values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0; 878da80777bSKarl Rupp values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0; 879da80777bSKarl Rupp values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0; 880da80777bSKarl Rupp values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0; 881da80777bSKarl Rupp values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0; 882da80777bSKarl Rupp values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0; 883da80777bSKarl Rupp values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0; 884da80777bSKarl Rupp values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0; 885da80777bSKarl Rupp values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0; 8861aa26658SKarl Rupp 88794ab13aaSBarry Smith ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr); 888552f7358SJed Brown } 889552f7358SJed Brown ierr = PetscLogFlops(152);CHKERRQ(ierr); 89056044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 89194ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 89294ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 893552f7358SJed Brown PetscFunctionReturn(0); 894552f7358SJed Brown } 895552f7358SJed Brown 896a6dfd86eSKarl Rupp PETSC_STATIC_INLINE PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 897a6dfd86eSKarl Rupp { 898fafc0619SMatthew G Knepley DM dmCoord; 899552f7358SJed Brown SNES snes; 900552f7358SJed Brown KSP ksp; 901552f7358SJed Brown PC pc; 902552f7358SJed Brown Vec coordsLocal, r, ref, real; 903552f7358SJed Brown Mat J; 90456044e6dSMatthew G. Knepley const PetscScalar *coords; 90556044e6dSMatthew G. Knepley PetscScalar *a; 906552f7358SJed Brown PetscInt p; 907552f7358SJed Brown PetscErrorCode ierr; 908552f7358SJed Brown 909552f7358SJed Brown PetscFunctionBegin; 910552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 911fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 912552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 913552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr); 914552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 915552f7358SJed Brown ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr); 916c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 917552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 918552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 919552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 920552f7358SJed Brown ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr); 921552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 922552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 9230298fd71SBarry Smith ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr); 9240298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr); 925552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 926552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 927552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 928552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 929552f7358SJed Brown 93056044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 931552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 932552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 933a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 934552f7358SJed Brown PetscScalar *xi; 935cb313848SJed Brown PetscReal xir[3]; 936552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 937552f7358SJed Brown 938552f7358SJed Brown /* Can make this do all points at once */ 9390298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 940ff1e0c32SBarry Smith if (8*3 != coordSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 8*3); 9410298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 942ff1e0c32SBarry Smith if (8*ctx->dof != xSize) SETERRQ2(ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %D", xSize, 8*ctx->dof); 9430298fd71SBarry Smith ierr = SNESSetFunction(snes, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 9440298fd71SBarry Smith ierr = SNESSetJacobian(snes, NULL, NULL, NULL, (void*) vertices);CHKERRQ(ierr); 945552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 946552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 947552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 948552f7358SJed Brown xi[2] = coords[p*ctx->dim+2]; 949552f7358SJed Brown ierr = VecRestoreArray(real, &xi);CHKERRQ(ierr); 950552f7358SJed Brown ierr = SNESSolve(snes, real, ref);CHKERRQ(ierr); 951552f7358SJed Brown ierr = VecGetArray(ref, &xi);CHKERRQ(ierr); 952cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 953cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 954cb313848SJed Brown xir[2] = PetscRealPart(xi[2]); 955552f7358SJed Brown for (comp = 0; comp < ctx->dof; ++comp) { 956552f7358SJed Brown a[p*ctx->dof+comp] = 957cb313848SJed Brown x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) + 9587a1931ceSMatthew G. Knepley x[3*ctx->dof+comp]* xir[0]*(1-xir[1])*(1-xir[2]) + 959cb313848SJed Brown x[2*ctx->dof+comp]* xir[0]* xir[1]*(1-xir[2]) + 9607a1931ceSMatthew G. Knepley x[1*ctx->dof+comp]*(1-xir[0])* xir[1]*(1-xir[2]) + 961cb313848SJed Brown x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])* xir[2] + 962cb313848SJed Brown x[5*ctx->dof+comp]* xir[0]*(1-xir[1])* xir[2] + 963cb313848SJed Brown x[6*ctx->dof+comp]* xir[0]* xir[1]* xir[2] + 964cb313848SJed Brown x[7*ctx->dof+comp]*(1-xir[0])* xir[1]* xir[2]; 965552f7358SJed Brown } 966552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 9670298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 9680298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 969552f7358SJed Brown } 970552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 97156044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 972552f7358SJed Brown 973552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 974552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 975552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 976552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 977552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 978552f7358SJed Brown PetscFunctionReturn(0); 979552f7358SJed Brown } 980552f7358SJed Brown 9814267b1a3SMatthew G. Knepley /*@C 9824267b1a3SMatthew G. Knepley DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points. 9834267b1a3SMatthew G. Knepley 984552f7358SJed Brown Input Parameters: 985552f7358SJed Brown + ctx - The DMInterpolationInfo context 986552f7358SJed Brown . dm - The DM 987552f7358SJed Brown - x - The local vector containing the field to be interpolated 988552f7358SJed Brown 989552f7358SJed Brown Output Parameters: 990552f7358SJed Brown . v - The vector containing the interpolated values 9914267b1a3SMatthew G. Knepley 9924267b1a3SMatthew G. Knepley Note: A suitable v can be obtained using DMInterpolationGetVector(). 9934267b1a3SMatthew G. Knepley 9944267b1a3SMatthew G. Knepley Level: beginner 9954267b1a3SMatthew G. Knepley 9964267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationAddPoints(), DMInterpolationCreate() 9974267b1a3SMatthew G. Knepley @*/ 9980adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v) 9990adebc6cSBarry Smith { 1000680d18d5SMatthew G. Knepley PetscInt n; 1001552f7358SJed Brown PetscErrorCode ierr; 1002552f7358SJed Brown 1003552f7358SJed Brown PetscFunctionBegin; 1004552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1005552f7358SJed Brown PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 1006552f7358SJed Brown PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 1007552f7358SJed Brown ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr); 1008ff1e0c32SBarry 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); 1009552f7358SJed Brown if (n) { 1010680d18d5SMatthew G. Knepley PetscDS ds; 1011680d18d5SMatthew G. Knepley DMPolytopeType ct; 1012680d18d5SMatthew G. Knepley PetscBool done = PETSC_FALSE; 1013680d18d5SMatthew G. Knepley 1014680d18d5SMatthew G. Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 1015680d18d5SMatthew G. Knepley if (ds) { 1016680d18d5SMatthew G. Knepley const PetscScalar *coords; 1017680d18d5SMatthew G. Knepley PetscScalar *interpolant; 1018680d18d5SMatthew G. Knepley PetscInt cdim, d, p, Nf, field, c = 0; 1019680d18d5SMatthew G. Knepley 1020680d18d5SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 1021680d18d5SMatthew G. Knepley ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 1022680d18d5SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 1023680d18d5SMatthew G. Knepley PetscTabulation T; 1024680d18d5SMatthew G. Knepley PetscFE fe; 1025680d18d5SMatthew G. Knepley PetscClassId id; 1026680d18d5SMatthew G. Knepley PetscReal xi[3]; 1027680d18d5SMatthew G. Knepley PetscInt Nc, f, fc; 1028680d18d5SMatthew G. Knepley 1029680d18d5SMatthew G. Knepley ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr); 1030680d18d5SMatthew G. Knepley ierr = PetscObjectGetClassId((PetscObject) fe, &id);CHKERRQ(ierr); 1031680d18d5SMatthew G. Knepley if (id != PETSCFE_CLASSID) break; 1032680d18d5SMatthew G. Knepley ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1033680d18d5SMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 1034680d18d5SMatthew G. Knepley ierr = VecGetArrayWrite(v, &interpolant);CHKERRQ(ierr); 1035680d18d5SMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 1036680d18d5SMatthew G. Knepley PetscScalar *xa = NULL; 1037680d18d5SMatthew G. Knepley PetscReal pcoords[3]; 1038680d18d5SMatthew G. Knepley 103952aa1562SMatthew G. Knepley if (ctx->cells[p] < 0) continue; 1040680d18d5SMatthew G. Knepley for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p*cdim+d]); 1041680d18d5SMatthew G. Knepley ierr = DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi);CHKERRQ(ierr); 1042680d18d5SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], NULL, &xa);CHKERRQ(ierr); 1043680d18d5SMatthew G. Knepley ierr = PetscFECreateTabulation(fe, 1, 1, xi, 0, &T);CHKERRQ(ierr); 1044680d18d5SMatthew G. Knepley { 1045680d18d5SMatthew G. Knepley const PetscReal *basis = T->T[0]; 1046680d18d5SMatthew G. Knepley const PetscInt Nb = T->Nb; 1047680d18d5SMatthew G. Knepley const PetscInt Nc = T->Nc; 1048680d18d5SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 1049680d18d5SMatthew G. Knepley interpolant[p*ctx->dof+c+fc] = 0.0; 1050680d18d5SMatthew G. Knepley for (f = 0; f < Nb; ++f) { 1051680d18d5SMatthew G. Knepley interpolant[p*ctx->dof+c+fc] += xa[f]*basis[(0*Nb + f)*Nc + fc]; 1052552f7358SJed Brown } 1053680d18d5SMatthew G. Knepley } 1054680d18d5SMatthew G. Knepley } 1055680d18d5SMatthew G. Knepley ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr); 1056680d18d5SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], NULL, &xa);CHKERRQ(ierr); 1057680d18d5SMatthew G. Knepley } 1058680d18d5SMatthew G. Knepley ierr = VecRestoreArrayWrite(v, &interpolant);CHKERRQ(ierr); 1059680d18d5SMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 1060680d18d5SMatthew G. Knepley c += Nc; 1061680d18d5SMatthew G. Knepley } 1062680d18d5SMatthew G. Knepley if (field == Nf) { 1063680d18d5SMatthew G. Knepley done = PETSC_TRUE; 1064680d18d5SMatthew G. Knepley if (c != ctx->dof) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %D != %D dof specified for interpolation", c, ctx->dof); 1065680d18d5SMatthew G. Knepley } 1066680d18d5SMatthew G. Knepley } 1067680d18d5SMatthew G. Knepley if (!done) { 1068680d18d5SMatthew G. Knepley /* TODO Check each cell individually */ 1069680d18d5SMatthew G. Knepley ierr = DMPlexGetCellType(dm, ctx->cells[0], &ct);CHKERRQ(ierr); 1070680d18d5SMatthew G. Knepley switch (ct) { 1071680d18d5SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1072680d18d5SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1073680d18d5SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1074680d18d5SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1075680d18d5SMatthew G. Knepley default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support fpr cell type %s", DMPolytopeTypes[ct]); 1076680d18d5SMatthew G. Knepley } 1077680d18d5SMatthew G. Knepley } 1078552f7358SJed Brown } 1079552f7358SJed Brown PetscFunctionReturn(0); 1080552f7358SJed Brown } 1081552f7358SJed Brown 10824267b1a3SMatthew G. Knepley /*@C 10834267b1a3SMatthew G. Knepley DMInterpolationDestroy - Destroys a DMInterpolationInfo context 10844267b1a3SMatthew G. Knepley 10854267b1a3SMatthew G. Knepley Collective on ctx 10864267b1a3SMatthew G. Knepley 10874267b1a3SMatthew G. Knepley Input Parameter: 10884267b1a3SMatthew G. Knepley . ctx - the context 10894267b1a3SMatthew G. Knepley 10904267b1a3SMatthew G. Knepley Level: beginner 10914267b1a3SMatthew G. Knepley 10924267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 10934267b1a3SMatthew G. Knepley @*/ 10940adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx) 10950adebc6cSBarry Smith { 1096552f7358SJed Brown PetscErrorCode ierr; 1097552f7358SJed Brown 1098552f7358SJed Brown PetscFunctionBegin; 1099552f7358SJed Brown PetscValidPointer(ctx, 2); 1100552f7358SJed Brown ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr); 1101552f7358SJed Brown ierr = PetscFree((*ctx)->points);CHKERRQ(ierr); 1102552f7358SJed Brown ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr); 1103552f7358SJed Brown ierr = PetscFree(*ctx);CHKERRQ(ierr); 11040298fd71SBarry Smith *ctx = NULL; 1105552f7358SJed Brown PetscFunctionReturn(0); 1106552f7358SJed Brown } 1107cc0c4584SMatthew G. Knepley 1108cc0c4584SMatthew G. Knepley /*@C 1109cc0c4584SMatthew G. Knepley SNESMonitorFields - Monitors the residual for each field separately 1110cc0c4584SMatthew G. Knepley 1111cc0c4584SMatthew G. Knepley Collective on SNES 1112cc0c4584SMatthew G. Knepley 1113cc0c4584SMatthew G. Knepley Input Parameters: 1114cc0c4584SMatthew G. Knepley + snes - the SNES context 1115cc0c4584SMatthew G. Knepley . its - iteration number 1116cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual 1117d43b4f6eSBarry Smith - vf - PetscViewerAndFormat of type ASCII 1118cc0c4584SMatthew G. Knepley 1119cc0c4584SMatthew G. Knepley Notes: 1120cc0c4584SMatthew G. Knepley This routine prints the residual norm at each iteration. 1121cc0c4584SMatthew G. Knepley 1122cc0c4584SMatthew G. Knepley Level: intermediate 1123cc0c4584SMatthew G. Knepley 1124cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault() 1125cc0c4584SMatthew G. Knepley @*/ 1126d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 1127cc0c4584SMatthew G. Knepley { 1128d43b4f6eSBarry Smith PetscViewer viewer = vf->viewer; 1129cc0c4584SMatthew G. Knepley Vec res; 1130cc0c4584SMatthew G. Knepley DM dm; 1131cc0c4584SMatthew G. Knepley PetscSection s; 1132cc0c4584SMatthew G. Knepley const PetscScalar *r; 1133cc0c4584SMatthew G. Knepley PetscReal *lnorms, *norms; 1134cc0c4584SMatthew G. Knepley PetscInt numFields, f, pStart, pEnd, p; 1135cc0c4584SMatthew G. Knepley PetscErrorCode ierr; 1136cc0c4584SMatthew G. Knepley 1137cc0c4584SMatthew G. Knepley PetscFunctionBegin; 11384d4332d5SBarry Smith PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 11399e5d0892SLisandro Dalcin ierr = SNESGetFunction(snes, &res, NULL, NULL);CHKERRQ(ierr); 1140cc0c4584SMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 114192fd8e1eSJed Brown ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 1142cc0c4584SMatthew G. Knepley ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr); 1143cc0c4584SMatthew G. Knepley ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1144cc0c4584SMatthew G. Knepley ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr); 1145cc0c4584SMatthew G. Knepley ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr); 1146cc0c4584SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1147cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 1148cc0c4584SMatthew G. Knepley PetscInt fdof, foff, d; 1149cc0c4584SMatthew G. Knepley 1150cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr); 1151cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr); 1152cc0c4584SMatthew G. Knepley for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d])); 1153cc0c4584SMatthew G. Knepley } 1154cc0c4584SMatthew G. Knepley } 1155cc0c4584SMatthew G. Knepley ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr); 1156*820f2d46SBarry Smith ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 1157d43b4f6eSBarry Smith ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1158cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 1159cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr); 1160cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 1161cc0c4584SMatthew G. Knepley if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1162cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr); 1163cc0c4584SMatthew G. Knepley } 1164cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr); 1165cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 1166d43b4f6eSBarry Smith ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1167cc0c4584SMatthew G. Knepley ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr); 1168cc0c4584SMatthew G. Knepley PetscFunctionReturn(0); 1169cc0c4584SMatthew G. Knepley } 117024cdb843SMatthew G. Knepley 117124cdb843SMatthew G. Knepley /********************* Residual Computation **************************/ 117224cdb843SMatthew G. Knepley 11736528b96dSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 11746528b96dSMatthew G. Knepley { 11756528b96dSMatthew G. Knepley PetscInt depth; 11766528b96dSMatthew G. Knepley PetscErrorCode ierr; 11776528b96dSMatthew G. Knepley 11786528b96dSMatthew G. Knepley PetscFunctionBegin; 11796528b96dSMatthew G. Knepley ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 11806528b96dSMatthew G. Knepley ierr = DMGetStratumIS(plex, "dim", depth, cellIS);CHKERRQ(ierr); 11816528b96dSMatthew G. Knepley if (!*cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, cellIS);CHKERRQ(ierr);} 11826528b96dSMatthew G. Knepley PetscFunctionReturn(0); 11836528b96dSMatthew G. Knepley } 11846528b96dSMatthew G. Knepley 118524cdb843SMatthew G. Knepley /*@ 118624cdb843SMatthew G. Knepley DMPlexSNESComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 118724cdb843SMatthew G. Knepley 118824cdb843SMatthew G. Knepley Input Parameters: 118924cdb843SMatthew G. Knepley + dm - The mesh 119024cdb843SMatthew G. Knepley . X - Local solution 119124cdb843SMatthew G. Knepley - user - The user context 119224cdb843SMatthew G. Knepley 119324cdb843SMatthew G. Knepley Output Parameter: 119424cdb843SMatthew G. Knepley . F - Local output vector 119524cdb843SMatthew G. Knepley 119624cdb843SMatthew G. Knepley Level: developer 119724cdb843SMatthew G. Knepley 11987a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 119924cdb843SMatthew G. Knepley @*/ 120024cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 120124cdb843SMatthew G. Knepley { 12026da023fcSToby Isaac DM plex; 1203083401c6SMatthew G. Knepley IS allcellIS; 12046528b96dSMatthew G. Knepley PetscInt Nds, s; 120524cdb843SMatthew G. Knepley PetscErrorCode ierr; 120624cdb843SMatthew G. Knepley 120724cdb843SMatthew G. Knepley PetscFunctionBegin; 12086da023fcSToby Isaac ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 12096528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 12106528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 12116528b96dSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 12126528b96dSMatthew G. Knepley PetscDS ds; 12136528b96dSMatthew G. Knepley IS cellIS; 12146528b96dSMatthew G. Knepley PetscHashFormKey key; 12156528b96dSMatthew G. Knepley 12166528b96dSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr); 12176528b96dSMatthew G. Knepley key.value = 0; 12186528b96dSMatthew G. Knepley key.field = 0; 12196528b96dSMatthew G. Knepley if (!key.label) { 12206528b96dSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 12216528b96dSMatthew G. Knepley cellIS = allcellIS; 12226528b96dSMatthew G. Knepley } else { 12236528b96dSMatthew G. Knepley IS pointIS; 12246528b96dSMatthew G. Knepley 12256528b96dSMatthew G. Knepley key.value = 1; 12266528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr); 12276528b96dSMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 12286528b96dSMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 12296528b96dSMatthew G. Knepley } 12306528b96dSMatthew G. Knepley ierr = DMPlexComputeResidual_Internal(plex, key, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr); 12316528b96dSMatthew G. Knepley ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 12326528b96dSMatthew G. Knepley } 12336528b96dSMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 12346528b96dSMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 12356528b96dSMatthew G. Knepley PetscFunctionReturn(0); 12366528b96dSMatthew G. Knepley } 12376528b96dSMatthew G. Knepley 12386528b96dSMatthew G. Knepley PetscErrorCode DMSNESComputeResidual(DM dm, Vec X, Vec F, void *user) 12396528b96dSMatthew G. Knepley { 12406528b96dSMatthew G. Knepley DM plex; 12416528b96dSMatthew G. Knepley IS allcellIS; 12426528b96dSMatthew G. Knepley PetscInt Nds, s; 12436528b96dSMatthew G. Knepley PetscErrorCode ierr; 12446528b96dSMatthew G. Knepley 12456528b96dSMatthew G. Knepley PetscFunctionBegin; 12466528b96dSMatthew G. Knepley ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 12476528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 12486528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1249083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1250083401c6SMatthew G. Knepley PetscDS ds; 1251083401c6SMatthew G. Knepley DMLabel label; 1252083401c6SMatthew G. Knepley IS cellIS; 1253083401c6SMatthew G. Knepley 1254083401c6SMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr); 12556528b96dSMatthew G. Knepley { 12566528b96dSMatthew G. Knepley PetscHMapForm resmap[2] = {ds->wf->f0, ds->wf->f1}; 12576528b96dSMatthew G. Knepley PetscWeakForm wf; 12586528b96dSMatthew G. Knepley PetscInt Nm = 2, m, Nk = 0, k, kp, off = 0; 12596528b96dSMatthew G. Knepley PetscHashFormKey *reskeys; 12606528b96dSMatthew G. Knepley 12616528b96dSMatthew G. Knepley /* Get unique residual keys */ 12626528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 12636528b96dSMatthew G. Knepley PetscInt Nkm; 12646528b96dSMatthew G. Knepley ierr = PetscHMapFormGetSize(resmap[m], &Nkm);CHKERRQ(ierr); 12656528b96dSMatthew G. Knepley Nk += Nkm; 12666528b96dSMatthew G. Knepley } 12676528b96dSMatthew G. Knepley ierr = PetscMalloc1(Nk, &reskeys);CHKERRQ(ierr); 12686528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 12696528b96dSMatthew G. Knepley ierr = PetscHMapFormGetKeys(resmap[m], &off, reskeys);CHKERRQ(ierr); 12706528b96dSMatthew G. Knepley } 12716528b96dSMatthew G. Knepley if (off != Nk) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk); 12726528b96dSMatthew G. Knepley ierr = PetscHashFormKeySort(Nk, reskeys);CHKERRQ(ierr); 12736528b96dSMatthew G. Knepley for (k = 0, kp = 1; kp < Nk; ++kp) { 12746528b96dSMatthew G. Knepley if ((reskeys[k].label != reskeys[kp].label) || (reskeys[k].value != reskeys[kp].value)) { 12756528b96dSMatthew G. Knepley ++k; 12766528b96dSMatthew G. Knepley if (kp != k) reskeys[k] = reskeys[kp]; 12776528b96dSMatthew G. Knepley } 12786528b96dSMatthew G. Knepley } 12796528b96dSMatthew G. Knepley Nk = k; 12806528b96dSMatthew G. Knepley 12816528b96dSMatthew G. Knepley ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 12826528b96dSMatthew G. Knepley for (k = 0; k < Nk; ++k) { 12836528b96dSMatthew G. Knepley DMLabel label = reskeys[k].label; 12846528b96dSMatthew G. Knepley PetscInt val = reskeys[k].value; 12856528b96dSMatthew G. Knepley 1286083401c6SMatthew G. Knepley if (!label) { 1287083401c6SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 1288083401c6SMatthew G. Knepley cellIS = allcellIS; 1289083401c6SMatthew G. Knepley } else { 1290083401c6SMatthew G. Knepley IS pointIS; 1291083401c6SMatthew G. Knepley 12926528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr); 1293083401c6SMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 1294083401c6SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 12954a3e9fdbSToby Isaac } 12966528b96dSMatthew G. Knepley ierr = DMPlexComputeResidual_Internal(plex, reskeys[k], cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr); 12974a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 1298083401c6SMatthew G. Knepley } 12996528b96dSMatthew G. Knepley ierr = PetscFree(reskeys);CHKERRQ(ierr); 13006528b96dSMatthew G. Knepley } 13016528b96dSMatthew G. Knepley } 1302083401c6SMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 13039a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 130424cdb843SMatthew G. Knepley PetscFunctionReturn(0); 130524cdb843SMatthew G. Knepley } 130624cdb843SMatthew G. Knepley 1307bdd6f66aSToby Isaac /*@ 1308bdd6f66aSToby Isaac DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X 1309bdd6f66aSToby Isaac 1310bdd6f66aSToby Isaac Input Parameters: 1311bdd6f66aSToby Isaac + dm - The mesh 1312bdd6f66aSToby Isaac - user - The user context 1313bdd6f66aSToby Isaac 1314bdd6f66aSToby Isaac Output Parameter: 1315bdd6f66aSToby Isaac . X - Local solution 1316bdd6f66aSToby Isaac 1317bdd6f66aSToby Isaac Level: developer 1318bdd6f66aSToby Isaac 13197a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 1320bdd6f66aSToby Isaac @*/ 1321bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user) 1322bdd6f66aSToby Isaac { 1323bdd6f66aSToby Isaac DM plex; 1324bdd6f66aSToby Isaac PetscErrorCode ierr; 1325bdd6f66aSToby Isaac 1326bdd6f66aSToby Isaac PetscFunctionBegin; 1327bdd6f66aSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 1328bdd6f66aSToby Isaac ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr); 1329bdd6f66aSToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 1330bdd6f66aSToby Isaac PetscFunctionReturn(0); 1331bdd6f66aSToby Isaac } 1332bdd6f66aSToby Isaac 13337a73cf09SMatthew G. Knepley /*@ 13347a73cf09SMatthew G. Knepley DMPlexComputeJacobianAction - Form the local portion of the Jacobian action Z = J(X) Y at the local solution X using pointwise functions specified by the user. 13357a73cf09SMatthew G. Knepley 13367a73cf09SMatthew G. Knepley Input Parameters: 13377a73cf09SMatthew G. Knepley + dm - The mesh 13387a73cf09SMatthew G. Knepley . cellIS - 13397a73cf09SMatthew G. Knepley . t - The time 13407a73cf09SMatthew G. Knepley . X_tShift - The multiplier for the Jacobian with repsect to X_t 13417a73cf09SMatthew G. Knepley . X - Local solution vector 13427a73cf09SMatthew G. Knepley . X_t - Time-derivative of the local solution vector 13437a73cf09SMatthew G. Knepley . Y - Local input vector 13447a73cf09SMatthew G. Knepley - user - The user context 13457a73cf09SMatthew G. Knepley 13467a73cf09SMatthew G. Knepley Output Parameter: 13477a73cf09SMatthew G. Knepley . Z - Local output vector 13487a73cf09SMatthew G. Knepley 13497a73cf09SMatthew G. Knepley Note: 13507a73cf09SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 13517a73cf09SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 13527a73cf09SMatthew G. Knepley 13537a73cf09SMatthew G. Knepley Level: developer 13547a73cf09SMatthew G. Knepley 13557a73cf09SMatthew G. Knepley .seealso: FormFunctionLocal() 13567a73cf09SMatthew G. Knepley @*/ 13577a73cf09SMatthew G. Knepley PetscErrorCode DMPlexComputeJacobianAction(DM dm, IS cellIS, PetscReal t, PetscReal X_tShift, Vec X, Vec X_t, Vec Y, Vec Z, void *user) 1358a925c78cSMatthew G. Knepley { 1359a925c78cSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *) dm->data; 1360a925c78cSMatthew G. Knepley const char *name = "Jacobian"; 13619a2a23afSMatthew G. Knepley DM dmAux = NULL, plex, plexAux = NULL; 1362a6e0b375SMatthew G. Knepley DMEnclosureType encAux; 1363c330f8ffSToby Isaac Vec A; 1364a925c78cSMatthew G. Knepley PetscDS prob, probAux = NULL; 1365a925c78cSMatthew G. Knepley PetscQuadrature quad; 1366a925c78cSMatthew G. Knepley PetscSection section, globalSection, sectionAux; 1367a925c78cSMatthew G. Knepley PetscScalar *elemMat, *elemMatD, *u, *u_t, *a = NULL, *y, *z; 13689044fa66SMatthew G. Knepley PetscInt Nf, fieldI, fieldJ; 13694d0b9603SSander Arens PetscInt totDim, totDimAux = 0; 13709044fa66SMatthew G. Knepley const PetscInt *cells; 13719044fa66SMatthew G. Knepley PetscInt cStart, cEnd, numCells, c; 137275b37a90SMatthew G. Knepley PetscBool hasDyn; 1373c330f8ffSToby Isaac DMField coordField; 13746528b96dSMatthew G. Knepley PetscHashFormKey key; 1375a925c78cSMatthew G. Knepley PetscErrorCode ierr; 1376a925c78cSMatthew G. Knepley 1377a925c78cSMatthew G. Knepley PetscFunctionBegin; 1378a925c78cSMatthew G. Knepley ierr = PetscLogEventBegin(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 13797a73cf09SMatthew G. Knepley ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 13807a73cf09SMatthew G. Knepley if (!cellIS) { 13817a73cf09SMatthew G. Knepley PetscInt depth; 13827a73cf09SMatthew G. Knepley 13837a73cf09SMatthew G. Knepley ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 13847a73cf09SMatthew G. Knepley ierr = DMGetStratumIS(plex, "dim", depth, &cellIS);CHKERRQ(ierr); 13857a73cf09SMatthew G. Knepley if (!cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, &cellIS);CHKERRQ(ierr);} 13867a73cf09SMatthew G. Knepley } else { 13877a73cf09SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) cellIS);CHKERRQ(ierr); 13887a73cf09SMatthew G. Knepley } 13896528b96dSMatthew G. Knepley key.label = NULL; 13906528b96dSMatthew G. Knepley key.value = 0; 139192fd8e1eSJed Brown ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 1392e87a4003SBarry Smith ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr); 1393d28747ceSMatthew G. Knepley ierr = ISGetLocalSize(cellIS, &numCells);CHKERRQ(ierr); 1394d28747ceSMatthew G. Knepley ierr = ISGetPointRange(cellIS, &cStart, &cEnd, &cells);CHKERRQ(ierr); 1395d28747ceSMatthew G. Knepley ierr = DMGetCellDS(dm, cells ? cells[cStart] : cStart, &prob);CHKERRQ(ierr); 1396d28747ceSMatthew G. Knepley ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 1397a925c78cSMatthew G. Knepley ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1398a925c78cSMatthew G. Knepley ierr = PetscDSHasDynamicJacobian(prob, &hasDyn);CHKERRQ(ierr); 1399a925c78cSMatthew G. Knepley hasDyn = hasDyn && (X_tShift != 0.0) ? PETSC_TRUE : PETSC_FALSE; 14009a2a23afSMatthew G. Knepley ierr = DMGetAuxiliaryVec(dm, NULL, 0, &A);CHKERRQ(ierr); 14019a2a23afSMatthew G. Knepley if (A) { 14029a2a23afSMatthew G. Knepley ierr = VecGetDM(A, &dmAux);CHKERRQ(ierr); 1403a6e0b375SMatthew G. Knepley ierr = DMGetEnclosureRelation(dmAux, dm, &encAux);CHKERRQ(ierr); 14047a73cf09SMatthew G. Knepley ierr = DMConvert(dmAux, DMPLEX, &plexAux);CHKERRQ(ierr); 140592fd8e1eSJed Brown ierr = DMGetLocalSection(plexAux, §ionAux);CHKERRQ(ierr); 1406a925c78cSMatthew G. Knepley ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 1407a925c78cSMatthew G. Knepley ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 1408a925c78cSMatthew G. Knepley } 1409a925c78cSMatthew G. Knepley ierr = VecSet(Z, 0.0);CHKERRQ(ierr); 1410a925c78cSMatthew 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); 1411a925c78cSMatthew G. Knepley if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 14124a3e9fdbSToby Isaac ierr = DMGetCoordinateField(dm, &coordField);CHKERRQ(ierr); 1413a925c78cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 14149044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 14159044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 1416a925c78cSMatthew G. Knepley PetscScalar *x = NULL, *x_t = NULL; 1417a925c78cSMatthew G. Knepley PetscInt i; 1418a925c78cSMatthew G. Knepley 14199044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 14209044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) u[cind*totDim+i] = x[i]; 14219044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X, cell, NULL, &x);CHKERRQ(ierr); 1422a925c78cSMatthew G. Knepley if (X_t) { 14239044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 14249044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) u_t[cind*totDim+i] = x_t[i]; 14259044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, X_t, cell, NULL, &x_t);CHKERRQ(ierr); 1426a925c78cSMatthew G. Knepley } 1427a925c78cSMatthew G. Knepley if (dmAux) { 142844171101SMatthew G. Knepley PetscInt subcell; 1429a6e0b375SMatthew G. Knepley ierr = DMGetEnclosurePoint(dmAux, dm, encAux, cell, &subcell);CHKERRQ(ierr); 143044171101SMatthew G. Knepley ierr = DMPlexVecGetClosure(plexAux, sectionAux, A, subcell, NULL, &x);CHKERRQ(ierr); 14319044fa66SMatthew G. Knepley for (i = 0; i < totDimAux; ++i) a[cind*totDimAux+i] = x[i]; 143244171101SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(plexAux, sectionAux, A, subcell, NULL, &x);CHKERRQ(ierr); 1433a925c78cSMatthew G. Knepley } 14349044fa66SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr); 14359044fa66SMatthew G. Knepley for (i = 0; i < totDim; ++i) y[cind*totDim+i] = x[i]; 14369044fa66SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, section, Y, cell, NULL, &x);CHKERRQ(ierr); 1437a925c78cSMatthew G. Knepley } 1438580bdb30SBarry Smith ierr = PetscArrayzero(elemMat, numCells*totDim*totDim);CHKERRQ(ierr); 1439580bdb30SBarry Smith if (hasDyn) {ierr = PetscArrayzero(elemMatD, numCells*totDim*totDim);CHKERRQ(ierr);} 1440a925c78cSMatthew G. Knepley for (fieldI = 0; fieldI < Nf; ++fieldI) { 1441a925c78cSMatthew G. Knepley PetscFE fe; 1442c330f8ffSToby Isaac PetscInt Nb; 1443a925c78cSMatthew G. Knepley /* Conforming batches */ 1444a925c78cSMatthew G. Knepley PetscInt numChunks, numBatches, numBlocks, Ne, blockSize, batchSize; 1445a925c78cSMatthew G. Knepley /* Remainder */ 1446c330f8ffSToby Isaac PetscInt Nr, offset, Nq; 1447c330f8ffSToby Isaac PetscQuadrature qGeom = NULL; 1448b7260050SToby Isaac PetscInt maxDegree; 1449c330f8ffSToby Isaac PetscFEGeom *cgeomFEM, *chunkGeom = NULL, *remGeom = NULL; 1450a925c78cSMatthew G. Knepley 1451a925c78cSMatthew G. Knepley ierr = PetscDSGetDiscretization(prob, fieldI, (PetscObject *) &fe);CHKERRQ(ierr); 1452a925c78cSMatthew G. Knepley ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 1453a925c78cSMatthew G. Knepley ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 1454a925c78cSMatthew G. Knepley ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 1455b7260050SToby Isaac ierr = DMFieldGetDegree(coordField,cellIS,NULL,&maxDegree);CHKERRQ(ierr); 1456b7260050SToby Isaac if (maxDegree <= 1) {ierr = DMFieldCreateDefaultQuadrature(coordField,cellIS,&qGeom);CHKERRQ(ierr);} 1457c330f8ffSToby Isaac if (!qGeom) { 1458c330f8ffSToby Isaac ierr = PetscFEGetQuadrature(fe,&qGeom);CHKERRQ(ierr); 1459c330f8ffSToby Isaac ierr = PetscObjectReference((PetscObject)qGeom);CHKERRQ(ierr); 1460c330f8ffSToby Isaac } 1461c330f8ffSToby Isaac ierr = PetscQuadratureGetData(qGeom, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 14624a3e9fdbSToby Isaac ierr = DMSNESGetFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 1463c330f8ffSToby Isaac blockSize = Nb; 1464a925c78cSMatthew G. Knepley batchSize = numBlocks * blockSize; 1465a925c78cSMatthew G. Knepley ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 1466a925c78cSMatthew G. Knepley numChunks = numCells / (numBatches*batchSize); 1467a925c78cSMatthew G. Knepley Ne = numChunks*numBatches*batchSize; 1468a925c78cSMatthew G. Knepley Nr = numCells % (numBatches*batchSize); 1469a925c78cSMatthew G. Knepley offset = numCells - Nr; 1470c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 1471c330f8ffSToby Isaac ierr = PetscFEGeomGetChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr); 1472a925c78cSMatthew G. Knepley for (fieldJ = 0; fieldJ < Nf; ++fieldJ) { 14736528b96dSMatthew G. Knepley key.field = fieldI*Nf + fieldJ; 14746528b96dSMatthew G. Knepley ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMat);CHKERRQ(ierr); 14756528b96dSMatthew G. Knepley ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN, key, 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); 1476a925c78cSMatthew G. Knepley if (hasDyn) { 14776528b96dSMatthew G. Knepley ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN_DYN, key, Ne, chunkGeom, u, u_t, probAux, a, t, X_tShift, elemMatD);CHKERRQ(ierr); 14786528b96dSMatthew G. Knepley ierr = PetscFEIntegrateJacobian(prob, PETSCFE_JACOBIAN_DYN, key, 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); 1479a925c78cSMatthew G. Knepley } 1480a925c78cSMatthew G. Knepley } 1481c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,offset,numCells,&remGeom);CHKERRQ(ierr); 1482c330f8ffSToby Isaac ierr = PetscFEGeomRestoreChunk(cgeomFEM,0,offset,&chunkGeom);CHKERRQ(ierr); 14834a3e9fdbSToby Isaac ierr = DMSNESRestoreFEGeom(coordField,cellIS,qGeom,PETSC_FALSE,&cgeomFEM);CHKERRQ(ierr); 1484c330f8ffSToby Isaac ierr = PetscQuadratureDestroy(&qGeom);CHKERRQ(ierr); 1485a925c78cSMatthew G. Knepley } 1486a925c78cSMatthew G. Knepley if (hasDyn) { 14879044fa66SMatthew G. Knepley for (c = 0; c < numCells*totDim*totDim; ++c) elemMat[c] += X_tShift*elemMatD[c]; 1488a925c78cSMatthew G. Knepley } 1489a925c78cSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 14909044fa66SMatthew G. Knepley const PetscInt cell = cells ? cells[c] : c; 14919044fa66SMatthew G. Knepley const PetscInt cind = c - cStart; 1492a925c78cSMatthew G. Knepley const PetscBLASInt M = totDim, one = 1; 1493a925c78cSMatthew G. Knepley const PetscScalar a = 1.0, b = 0.0; 1494a925c78cSMatthew G. Knepley 14959044fa66SMatthew G. Knepley PetscStackCallBLAS("BLASgemv", BLASgemv_("N", &M, &M, &a, &elemMat[cind*totDim*totDim], &M, &y[cind*totDim], &one, &b, z, &one)); 1496a925c78cSMatthew G. Knepley if (mesh->printFEM > 1) { 14979044fa66SMatthew G. Knepley ierr = DMPrintCellMatrix(c, name, totDim, totDim, &elemMat[cind*totDim*totDim]);CHKERRQ(ierr); 14989044fa66SMatthew G. Knepley ierr = DMPrintCellVector(c, "Y", totDim, &y[cind*totDim]);CHKERRQ(ierr); 1499a925c78cSMatthew G. Knepley ierr = DMPrintCellVector(c, "Z", totDim, z);CHKERRQ(ierr); 1500a925c78cSMatthew G. Knepley } 15019044fa66SMatthew G. Knepley ierr = DMPlexVecSetClosure(dm, section, Z, cell, z, ADD_VALUES);CHKERRQ(ierr); 1502a925c78cSMatthew G. Knepley } 1503a925c78cSMatthew G. Knepley ierr = PetscFree6(u,u_t,elemMat,elemMatD,y,z);CHKERRQ(ierr); 1504a925c78cSMatthew G. Knepley if (mesh->printFEM) { 1505ea13f565SStefano Zampini ierr = PetscPrintf(PetscObjectComm((PetscObject)Z), "Z:\n");CHKERRQ(ierr); 1506a8c5bd36SStefano Zampini ierr = VecView(Z, NULL);CHKERRQ(ierr); 1507a925c78cSMatthew G. Knepley } 15087a73cf09SMatthew G. Knepley ierr = PetscFree(a);CHKERRQ(ierr); 15097a73cf09SMatthew G. Knepley ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 15107a73cf09SMatthew G. Knepley ierr = DMDestroy(&plexAux);CHKERRQ(ierr); 15117a73cf09SMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 1512a925c78cSMatthew G. Knepley ierr = PetscLogEventEnd(DMPLEX_JacobianFEM,dm,0,0,0);CHKERRQ(ierr); 1513a925c78cSMatthew G. Knepley PetscFunctionReturn(0); 1514a925c78cSMatthew G. Knepley } 1515a925c78cSMatthew G. Knepley 151624cdb843SMatthew G. Knepley /*@ 151724cdb843SMatthew G. Knepley DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 151824cdb843SMatthew G. Knepley 151924cdb843SMatthew G. Knepley Input Parameters: 152024cdb843SMatthew G. Knepley + dm - The mesh 152124cdb843SMatthew G. Knepley . X - Local input vector 152224cdb843SMatthew G. Knepley - user - The user context 152324cdb843SMatthew G. Knepley 152424cdb843SMatthew G. Knepley Output Parameter: 152524cdb843SMatthew G. Knepley . Jac - Jacobian matrix 152624cdb843SMatthew G. Knepley 152724cdb843SMatthew G. Knepley Note: 152824cdb843SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 152924cdb843SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 153024cdb843SMatthew G. Knepley 153124cdb843SMatthew G. Knepley Level: developer 153224cdb843SMatthew G. Knepley 153324cdb843SMatthew G. Knepley .seealso: FormFunctionLocal() 153424cdb843SMatthew G. Knepley @*/ 153524cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user) 153624cdb843SMatthew G. Knepley { 15376da023fcSToby Isaac DM plex; 1538083401c6SMatthew G. Knepley IS allcellIS; 1539f04eb4edSMatthew G. Knepley PetscBool hasJac, hasPrec; 15406528b96dSMatthew G. Knepley PetscInt Nds, s; 154124cdb843SMatthew G. Knepley PetscErrorCode ierr; 154224cdb843SMatthew G. Knepley 154324cdb843SMatthew G. Knepley PetscFunctionBegin; 15446da023fcSToby Isaac ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 15456528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 15466528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1547083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1548083401c6SMatthew G. Knepley PetscDS ds; 1549083401c6SMatthew G. Knepley IS cellIS; 15506528b96dSMatthew G. Knepley PetscHashFormKey key; 1551083401c6SMatthew G. Knepley 15526528b96dSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr); 15536528b96dSMatthew G. Knepley key.value = 0; 15546528b96dSMatthew G. Knepley key.field = 0; 15556528b96dSMatthew G. Knepley if (!key.label) { 1556083401c6SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 1557083401c6SMatthew G. Knepley cellIS = allcellIS; 1558083401c6SMatthew G. Knepley } else { 1559083401c6SMatthew G. Knepley IS pointIS; 1560083401c6SMatthew G. Knepley 15616528b96dSMatthew G. Knepley key.value = 1; 15626528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr); 1563083401c6SMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 1564083401c6SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1565083401c6SMatthew G. Knepley } 1566083401c6SMatthew G. Knepley if (!s) { 1567083401c6SMatthew G. Knepley ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr); 1568083401c6SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr); 1569f04eb4edSMatthew G. Knepley if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);} 1570f04eb4edSMatthew G. Knepley ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 1571083401c6SMatthew G. Knepley } 15726528b96dSMatthew G. Knepley ierr = DMPlexComputeJacobian_Internal(plex, key, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr); 15734a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 1574083401c6SMatthew G. Knepley } 1575083401c6SMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 15769a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 157724cdb843SMatthew G. Knepley PetscFunctionReturn(0); 157824cdb843SMatthew G. Knepley } 15791878804aSMatthew G. Knepley 158038cfc46eSPierre Jolivet /* 158138cfc46eSPierre Jolivet MatComputeNeumannOverlap - Computes an unassembled (Neumann) local overlapping Mat in nonlinear context. 158238cfc46eSPierre Jolivet 158338cfc46eSPierre Jolivet Input Parameters: 158438cfc46eSPierre Jolivet + X - SNES linearization point 158538cfc46eSPierre Jolivet . ovl - index set of overlapping subdomains 158638cfc46eSPierre Jolivet 158738cfc46eSPierre Jolivet Output Parameter: 158838cfc46eSPierre Jolivet . J - unassembled (Neumann) local matrix 158938cfc46eSPierre Jolivet 159038cfc46eSPierre Jolivet Level: intermediate 159138cfc46eSPierre Jolivet 159238cfc46eSPierre Jolivet .seealso: DMCreateNeumannOverlap(), MATIS, PCHPDDMSetAuxiliaryMat() 159338cfc46eSPierre Jolivet */ 159438cfc46eSPierre Jolivet static PetscErrorCode MatComputeNeumannOverlap_Plex(Mat J, PetscReal t, Vec X, Vec X_t, PetscReal s, IS ovl, void *ctx) 159538cfc46eSPierre Jolivet { 159638cfc46eSPierre Jolivet SNES snes; 159738cfc46eSPierre Jolivet Mat pJ; 159838cfc46eSPierre Jolivet DM ovldm,origdm; 159938cfc46eSPierre Jolivet DMSNES sdm; 160038cfc46eSPierre Jolivet PetscErrorCode (*bfun)(DM,Vec,void*); 160138cfc46eSPierre Jolivet PetscErrorCode (*jfun)(DM,Vec,Mat,Mat,void*); 160238cfc46eSPierre Jolivet void *bctx,*jctx; 160338cfc46eSPierre Jolivet PetscErrorCode ierr; 160438cfc46eSPierre Jolivet 160538cfc46eSPierre Jolivet PetscFunctionBegin; 160638cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_MATIS",(PetscObject*)&pJ);CHKERRQ(ierr); 160738cfc46eSPierre Jolivet if (!pJ) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing overlapping Mat");CHKERRQ(ierr); 160838cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Original_HPDDM",(PetscObject*)&origdm);CHKERRQ(ierr); 160938cfc46eSPierre Jolivet if (!origdm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing original DM");CHKERRQ(ierr); 161038cfc46eSPierre Jolivet ierr = MatGetDM(pJ,&ovldm);CHKERRQ(ierr); 161138cfc46eSPierre Jolivet ierr = DMSNESGetBoundaryLocal(origdm,&bfun,&bctx);CHKERRQ(ierr); 161238cfc46eSPierre Jolivet ierr = DMSNESSetBoundaryLocal(ovldm,bfun,bctx);CHKERRQ(ierr); 161338cfc46eSPierre Jolivet ierr = DMSNESGetJacobianLocal(origdm,&jfun,&jctx);CHKERRQ(ierr); 161438cfc46eSPierre Jolivet ierr = DMSNESSetJacobianLocal(ovldm,jfun,jctx);CHKERRQ(ierr); 161538cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject*)&snes);CHKERRQ(ierr); 161638cfc46eSPierre Jolivet if (!snes) { 161738cfc46eSPierre Jolivet ierr = SNESCreate(PetscObjectComm((PetscObject)ovl),&snes);CHKERRQ(ierr); 161838cfc46eSPierre Jolivet ierr = SNESSetDM(snes,ovldm);CHKERRQ(ierr); 161938cfc46eSPierre Jolivet ierr = PetscObjectCompose((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject)snes);CHKERRQ(ierr); 162038cfc46eSPierre Jolivet ierr = PetscObjectDereference((PetscObject)snes);CHKERRQ(ierr); 162138cfc46eSPierre Jolivet } 162238cfc46eSPierre Jolivet ierr = DMGetDMSNES(ovldm,&sdm);CHKERRQ(ierr); 162338cfc46eSPierre Jolivet ierr = VecLockReadPush(X);CHKERRQ(ierr); 162438cfc46eSPierre Jolivet PetscStackPush("SNES user Jacobian function"); 162538cfc46eSPierre Jolivet ierr = (*sdm->ops->computejacobian)(snes,X,pJ,pJ,sdm->jacobianctx);CHKERRQ(ierr); 162638cfc46eSPierre Jolivet PetscStackPop; 162738cfc46eSPierre Jolivet ierr = VecLockReadPop(X);CHKERRQ(ierr); 162838cfc46eSPierre Jolivet /* this is a no-hop, just in case we decide to change the placeholder for the local Neumann matrix */ 162938cfc46eSPierre Jolivet { 163038cfc46eSPierre Jolivet Mat locpJ; 163138cfc46eSPierre Jolivet 163238cfc46eSPierre Jolivet ierr = MatISGetLocalMat(pJ,&locpJ);CHKERRQ(ierr); 163338cfc46eSPierre Jolivet ierr = MatCopy(locpJ,J,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 163438cfc46eSPierre Jolivet } 163538cfc46eSPierre Jolivet PetscFunctionReturn(0); 163638cfc46eSPierre Jolivet } 163738cfc46eSPierre Jolivet 1638a925c78cSMatthew G. Knepley /*@ 16399f520fc2SToby Isaac DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian. 16409f520fc2SToby Isaac 16419f520fc2SToby Isaac Input Parameters: 16429f520fc2SToby Isaac + dm - The DM object 1643dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary()) 16449f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual()) 16459f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian()) 16461a244344SSatish Balay 16471a244344SSatish Balay Level: developer 16489f520fc2SToby Isaac @*/ 16499f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx) 16509f520fc2SToby Isaac { 16519f520fc2SToby Isaac PetscErrorCode ierr; 16529f520fc2SToby Isaac 16539f520fc2SToby Isaac PetscFunctionBegin; 16549f520fc2SToby Isaac ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr); 16559f520fc2SToby Isaac ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr); 16569f520fc2SToby Isaac ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr); 165738cfc46eSPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",MatComputeNeumannOverlap_Plex);CHKERRQ(ierr); 16589f520fc2SToby Isaac PetscFunctionReturn(0); 16599f520fc2SToby Isaac } 16609f520fc2SToby Isaac 1661f017bcb6SMatthew G. Knepley /*@C 1662f017bcb6SMatthew G. Knepley DMSNESCheckDiscretization - Check the discretization error of the exact solution 1663f017bcb6SMatthew G. Knepley 1664f017bcb6SMatthew G. Knepley Input Parameters: 1665f017bcb6SMatthew G. Knepley + snes - the SNES object 1666f017bcb6SMatthew G. Knepley . dm - the DM 1667f2cacb80SMatthew G. Knepley . t - the time 1668f017bcb6SMatthew G. Knepley . u - a DM vector 1669f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1670f017bcb6SMatthew G. Knepley 1671f3c94560SMatthew G. Knepley Output Parameters: 1672f3c94560SMatthew G. Knepley . error - An array which holds the discretization error in each field, or NULL 1673f3c94560SMatthew G. Knepley 16747f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 16757f96f943SMatthew G. Knepley 1676f017bcb6SMatthew G. Knepley Level: developer 1677f017bcb6SMatthew G. Knepley 16787f96f943SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckResidual(), DMSNESCheckJacobian(), PetscDSSetExactSolution() 1679f017bcb6SMatthew G. Knepley @*/ 1680f2cacb80SMatthew G. Knepley PetscErrorCode DMSNESCheckDiscretization(SNES snes, DM dm, PetscReal t, Vec u, PetscReal tol, PetscReal error[]) 16811878804aSMatthew G. Knepley { 1682f017bcb6SMatthew G. Knepley PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 1683f017bcb6SMatthew G. Knepley void **ectxs; 1684f3c94560SMatthew G. Knepley PetscReal *err; 16857f96f943SMatthew G. Knepley MPI_Comm comm; 16867f96f943SMatthew G. Knepley PetscInt Nf, f; 16871878804aSMatthew G. Knepley PetscErrorCode ierr; 16881878804aSMatthew G. Knepley 16891878804aSMatthew G. Knepley PetscFunctionBegin; 1690f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1691f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1692f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1693534a8f05SLisandro Dalcin if (error) PetscValidRealPointer(error, 6); 16947f96f943SMatthew G. Knepley 1695f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, t, u, NULL);CHKERRQ(ierr); 16967f96f943SMatthew G. Knepley ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr); 16977f96f943SMatthew G. Knepley 1698f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1699f017bcb6SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 1700083401c6SMatthew G. Knepley ierr = PetscCalloc3(Nf, &exacts, Nf, &ectxs, PetscMax(1, Nf), &err);CHKERRQ(ierr); 17017f96f943SMatthew G. Knepley { 17027f96f943SMatthew G. Knepley PetscInt Nds, s; 17037f96f943SMatthew G. Knepley 1704083401c6SMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1705083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 17067f96f943SMatthew G. Knepley PetscDS ds; 1707083401c6SMatthew G. Knepley DMLabel label; 1708083401c6SMatthew G. Knepley IS fieldIS; 17097f96f943SMatthew G. Knepley const PetscInt *fields; 17107f96f943SMatthew G. Knepley PetscInt dsNf, f; 1711083401c6SMatthew G. Knepley 1712083401c6SMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 1713083401c6SMatthew G. Knepley ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 1714083401c6SMatthew G. Knepley ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 1715083401c6SMatthew G. Knepley for (f = 0; f < dsNf; ++f) { 1716083401c6SMatthew G. Knepley const PetscInt field = fields[f]; 1717083401c6SMatthew G. Knepley ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 1718083401c6SMatthew G. Knepley } 1719083401c6SMatthew G. Knepley ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 1720083401c6SMatthew G. Knepley } 1721083401c6SMatthew G. Knepley } 1722f017bcb6SMatthew G. Knepley if (Nf > 1) { 1723f2cacb80SMatthew G. Knepley ierr = DMComputeL2FieldDiff(dm, t, exacts, ectxs, u, err);CHKERRQ(ierr); 1724f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 1725f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1726f3c94560SMatthew G. Knepley if (err[f] > tol) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g for field %D exceeds tolerance %g", (double) err[f], f, (double) tol); 17271878804aSMatthew G. Knepley } 1728b878532fSMatthew G. Knepley } else if (error) { 1729b878532fSMatthew G. Knepley for (f = 0; f < Nf; ++f) error[f] = err[f]; 17301878804aSMatthew G. Knepley } else { 1731f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr); 1732f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1733f017bcb6SMatthew G. Knepley if (f) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);} 1734f3c94560SMatthew G. Knepley ierr = PetscPrintf(comm, "%g", (double)err[f]);CHKERRQ(ierr); 17351878804aSMatthew G. Knepley } 1736f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr); 1737f017bcb6SMatthew G. Knepley } 1738f017bcb6SMatthew G. Knepley } else { 1739f2cacb80SMatthew G. Knepley ierr = DMComputeL2Diff(dm, t, exacts, ectxs, u, &err[0]);CHKERRQ(ierr); 1740f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 1741f3c94560SMatthew G. Knepley if (err[0] > tol) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g exceeds tolerance %g", (double) err[0], (double) tol); 1742b878532fSMatthew G. Knepley } else if (error) { 1743b878532fSMatthew G. Knepley error[0] = err[0]; 1744f017bcb6SMatthew G. Knepley } else { 1745f3c94560SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Error: %g\n", (double) err[0]);CHKERRQ(ierr); 1746f017bcb6SMatthew G. Knepley } 1747f017bcb6SMatthew G. Knepley } 1748f3c94560SMatthew G. Knepley ierr = PetscFree3(exacts, ectxs, err);CHKERRQ(ierr); 1749f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1750f017bcb6SMatthew G. Knepley } 1751f017bcb6SMatthew G. Knepley 1752f017bcb6SMatthew G. Knepley /*@C 1753f017bcb6SMatthew G. Knepley DMSNESCheckResidual - Check the residual of the exact solution 1754f017bcb6SMatthew G. Knepley 1755f017bcb6SMatthew G. Knepley Input Parameters: 1756f017bcb6SMatthew G. Knepley + snes - the SNES object 1757f017bcb6SMatthew G. Knepley . dm - the DM 1758f017bcb6SMatthew G. Knepley . u - a DM vector 1759f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1760f017bcb6SMatthew G. Knepley 1761f3c94560SMatthew G. Knepley Output Parameters: 1762f3c94560SMatthew G. Knepley . residual - The residual norm of the exact solution, or NULL 1763f3c94560SMatthew G. Knepley 1764f017bcb6SMatthew G. Knepley Level: developer 1765f017bcb6SMatthew G. Knepley 1766f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckJacobian() 1767f017bcb6SMatthew G. Knepley @*/ 1768f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckResidual(SNES snes, DM dm, Vec u, PetscReal tol, PetscReal *residual) 1769f017bcb6SMatthew G. Knepley { 1770f017bcb6SMatthew G. Knepley MPI_Comm comm; 1771f017bcb6SMatthew G. Knepley Vec r; 1772f017bcb6SMatthew G. Knepley PetscReal res; 1773f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1774f017bcb6SMatthew G. Knepley 1775f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1776f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1777f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1778f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1779534a8f05SLisandro Dalcin if (residual) PetscValidRealPointer(residual, 5); 1780f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1781f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr); 1782f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &r);CHKERRQ(ierr); 17831878804aSMatthew G. Knepley ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); 17841878804aSMatthew G. Knepley ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); 1785f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 1786f017bcb6SMatthew G. Knepley if (res > tol) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "L_2 Residual %g exceeds tolerance %g", (double) res, (double) tol); 1787b878532fSMatthew G. Knepley } else if (residual) { 1788b878532fSMatthew G. Knepley *residual = res; 1789f017bcb6SMatthew G. Knepley } else { 1790f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr); 17911878804aSMatthew G. Knepley ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); 17921878804aSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr); 1793685405a1SBarry Smith ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr); 1794685405a1SBarry Smith ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr); 1795f017bcb6SMatthew G. Knepley } 1796f017bcb6SMatthew G. Knepley ierr = VecDestroy(&r);CHKERRQ(ierr); 1797f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1798f017bcb6SMatthew G. Knepley } 1799f017bcb6SMatthew G. Knepley 1800f017bcb6SMatthew G. Knepley /*@C 1801f3c94560SMatthew G. Knepley DMSNESCheckJacobian - Check the Jacobian of the exact solution against the residual using the Taylor Test 1802f017bcb6SMatthew G. Knepley 1803f017bcb6SMatthew G. Knepley Input Parameters: 1804f017bcb6SMatthew G. Knepley + snes - the SNES object 1805f017bcb6SMatthew G. Knepley . dm - the DM 1806f017bcb6SMatthew G. Knepley . u - a DM vector 1807f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1808f017bcb6SMatthew G. Knepley 1809f3c94560SMatthew G. Knepley Output Parameters: 1810f3c94560SMatthew G. Knepley + isLinear - Flag indicaing that the function looks linear, or NULL 1811f3c94560SMatthew G. Knepley - convRate - The rate of convergence of the linear model, or NULL 1812f3c94560SMatthew G. Knepley 1813f017bcb6SMatthew G. Knepley Level: developer 1814f017bcb6SMatthew G. Knepley 1815f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckResidual() 1816f017bcb6SMatthew G. Knepley @*/ 1817f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckJacobian(SNES snes, DM dm, Vec u, PetscReal tol, PetscBool *isLinear, PetscReal *convRate) 1818f017bcb6SMatthew G. Knepley { 1819f017bcb6SMatthew G. Knepley MPI_Comm comm; 1820f017bcb6SMatthew G. Knepley PetscDS ds; 1821f017bcb6SMatthew G. Knepley Mat J, M; 1822f017bcb6SMatthew G. Knepley MatNullSpace nullspace; 1823f3c94560SMatthew G. Knepley PetscReal slope, intercept; 18247f96f943SMatthew G. Knepley PetscBool hasJac, hasPrec, isLin = PETSC_FALSE; 1825f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1826f017bcb6SMatthew G. Knepley 1827f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1828f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1829f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1830f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1831534a8f05SLisandro Dalcin if (isLinear) PetscValidBoolPointer(isLinear, 5); 1832534a8f05SLisandro Dalcin if (convRate) PetscValidRealPointer(convRate, 5); 1833f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1834f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr); 1835f017bcb6SMatthew G. Knepley /* Create and view matrices */ 1836f017bcb6SMatthew G. Knepley ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr); 18377f96f943SMatthew G. Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 1838f017bcb6SMatthew G. Knepley ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr); 1839f017bcb6SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr); 1840282e7bb4SMatthew G. Knepley if (hasJac && hasPrec) { 1841282e7bb4SMatthew G. Knepley ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr); 1842282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr); 1843f017bcb6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) M, "Preconditioning Matrix");CHKERRQ(ierr); 1844282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr); 1845282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr); 1846282e7bb4SMatthew G. Knepley ierr = MatDestroy(&M);CHKERRQ(ierr); 1847282e7bb4SMatthew G. Knepley } else { 1848282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr); 1849282e7bb4SMatthew G. Knepley } 1850f017bcb6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) J, "Jacobian");CHKERRQ(ierr); 1851282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr); 1852282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr); 1853f017bcb6SMatthew G. Knepley /* Check nullspace */ 1854f017bcb6SMatthew G. Knepley ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr); 1855f017bcb6SMatthew G. Knepley if (nullspace) { 18561878804aSMatthew G. Knepley PetscBool isNull; 1857f017bcb6SMatthew G. Knepley ierr = MatNullSpaceTest(nullspace, J, &isNull);CHKERRQ(ierr); 1858f017bcb6SMatthew G. Knepley if (!isNull) SETERRQ(comm, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid."); 18591878804aSMatthew G. Knepley } 1860f017bcb6SMatthew G. Knepley /* Taylor test */ 1861f017bcb6SMatthew G. Knepley { 1862f017bcb6SMatthew G. Knepley PetscRandom rand; 1863f017bcb6SMatthew G. Knepley Vec du, uhat, r, rhat, df; 1864f3c94560SMatthew G. Knepley PetscReal h; 1865f017bcb6SMatthew G. Knepley PetscReal *es, *hs, *errors; 1866f017bcb6SMatthew G. Knepley PetscReal hMax = 1.0, hMin = 1e-6, hMult = 0.1; 1867f017bcb6SMatthew G. Knepley PetscInt Nv, v; 1868f017bcb6SMatthew G. Knepley 1869f017bcb6SMatthew G. Knepley /* Choose a perturbation direction */ 1870f017bcb6SMatthew G. Knepley ierr = PetscRandomCreate(comm, &rand);CHKERRQ(ierr); 1871f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &du);CHKERRQ(ierr); 1872f017bcb6SMatthew G. Knepley ierr = VecSetRandom(du, rand);CHKERRQ(ierr); 1873f017bcb6SMatthew G. Knepley ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr); 1874f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &df);CHKERRQ(ierr); 1875f017bcb6SMatthew G. Knepley ierr = MatMult(J, du, df);CHKERRQ(ierr); 1876f017bcb6SMatthew G. Knepley /* Evaluate residual at u, F(u), save in vector r */ 1877f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &r);CHKERRQ(ierr); 1878f017bcb6SMatthew G. Knepley ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); 1879f017bcb6SMatthew G. Knepley /* Look at the convergence of our Taylor approximation as we approach u */ 1880f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv); 1881f017bcb6SMatthew G. Knepley ierr = PetscCalloc3(Nv, &es, Nv, &hs, Nv, &errors);CHKERRQ(ierr); 1882f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &uhat);CHKERRQ(ierr); 1883f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &rhat);CHKERRQ(ierr); 1884f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv) { 1885f017bcb6SMatthew G. Knepley ierr = VecWAXPY(uhat, h, du, u);CHKERRQ(ierr); 1886f017bcb6SMatthew G. Knepley /* F(\hat u) \approx F(u) + J(u) (uhat - u) = F(u) + h * J(u) du */ 1887f017bcb6SMatthew G. Knepley ierr = SNESComputeFunction(snes, uhat, rhat);CHKERRQ(ierr); 1888f017bcb6SMatthew G. Knepley ierr = VecAXPBYPCZ(rhat, -1.0, -h, 1.0, r, df);CHKERRQ(ierr); 1889f017bcb6SMatthew G. Knepley ierr = VecNorm(rhat, NORM_2, &errors[Nv]);CHKERRQ(ierr); 1890f017bcb6SMatthew G. Knepley 1891f017bcb6SMatthew G. Knepley es[Nv] = PetscLog10Real(errors[Nv]); 1892f017bcb6SMatthew G. Knepley hs[Nv] = PetscLog10Real(h); 1893f017bcb6SMatthew G. Knepley } 1894f017bcb6SMatthew G. Knepley ierr = VecDestroy(&uhat);CHKERRQ(ierr); 1895f017bcb6SMatthew G. Knepley ierr = VecDestroy(&rhat);CHKERRQ(ierr); 1896f017bcb6SMatthew G. Knepley ierr = VecDestroy(&df);CHKERRQ(ierr); 18971878804aSMatthew G. Knepley ierr = VecDestroy(&r);CHKERRQ(ierr); 1898f017bcb6SMatthew G. Knepley ierr = VecDestroy(&du);CHKERRQ(ierr); 1899f017bcb6SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1900f017bcb6SMatthew G. Knepley if ((tol >= 0) && (errors[v] > tol)) break; 1901f017bcb6SMatthew G. Knepley else if (errors[v] > PETSC_SMALL) break; 1902f017bcb6SMatthew G. Knepley } 1903f3c94560SMatthew G. Knepley if (v == Nv) isLin = PETSC_TRUE; 1904f017bcb6SMatthew G. Knepley ierr = PetscLinearRegression(Nv, hs, es, &slope, &intercept);CHKERRQ(ierr); 1905f017bcb6SMatthew G. Knepley ierr = PetscFree3(es, hs, errors);CHKERRQ(ierr); 1906f017bcb6SMatthew G. Knepley /* Slope should be about 2 */ 1907f017bcb6SMatthew G. Knepley if (tol >= 0) { 1908b878532fSMatthew G. Knepley if (!isLin && PetscAbsReal(2 - slope) > tol) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Taylor approximation convergence rate should be 2, not %0.2f", (double) slope); 1909b878532fSMatthew G. Knepley } else if (isLinear || convRate) { 1910b878532fSMatthew G. Knepley if (isLinear) *isLinear = isLin; 1911b878532fSMatthew G. Knepley if (convRate) *convRate = slope; 1912f017bcb6SMatthew G. Knepley } else { 1913f3c94560SMatthew G. Knepley if (!isLin) {ierr = PetscPrintf(comm, "Taylor approximation converging at order %3.2f\n", (double) slope);CHKERRQ(ierr);} 1914f017bcb6SMatthew G. Knepley else {ierr = PetscPrintf(comm, "Function appears to be linear\n");CHKERRQ(ierr);} 1915f017bcb6SMatthew G. Knepley } 1916f017bcb6SMatthew G. Knepley } 19171878804aSMatthew G. Knepley ierr = MatDestroy(&J);CHKERRQ(ierr); 19181878804aSMatthew G. Knepley PetscFunctionReturn(0); 19191878804aSMatthew G. Knepley } 19201878804aSMatthew G. Knepley 19217f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheck_Internal(SNES snes, DM dm, Vec u) 1922f017bcb6SMatthew G. Knepley { 1923f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1924f017bcb6SMatthew G. Knepley 1925f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1926f2cacb80SMatthew G. Knepley ierr = DMSNESCheckDiscretization(snes, dm, 0.0, u, -1.0, NULL);CHKERRQ(ierr); 1927f3c94560SMatthew G. Knepley ierr = DMSNESCheckResidual(snes, dm, u, -1.0, NULL);CHKERRQ(ierr); 1928f3c94560SMatthew G. Knepley ierr = DMSNESCheckJacobian(snes, dm, u, -1.0, NULL, NULL);CHKERRQ(ierr); 1929f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1930f017bcb6SMatthew G. Knepley } 1931f017bcb6SMatthew G. Knepley 1932bee9a294SMatthew G. Knepley /*@C 1933bee9a294SMatthew G. Knepley DMSNESCheckFromOptions - Check the residual and Jacobian functions using the exact solution by outputting some diagnostic information 1934bee9a294SMatthew G. Knepley 1935bee9a294SMatthew G. Knepley Input Parameters: 1936bee9a294SMatthew G. Knepley + snes - the SNES object 19377f96f943SMatthew G. Knepley - u - representative SNES vector 19387f96f943SMatthew G. Knepley 19397f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 1940bee9a294SMatthew G. Knepley 1941bee9a294SMatthew G. Knepley Level: developer 1942bee9a294SMatthew G. Knepley @*/ 19437f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u) 19441878804aSMatthew G. Knepley { 19451878804aSMatthew G. Knepley DM dm; 19461878804aSMatthew G. Knepley Vec sol; 19471878804aSMatthew G. Knepley PetscBool check; 19481878804aSMatthew G. Knepley PetscErrorCode ierr; 19491878804aSMatthew G. Knepley 19501878804aSMatthew G. Knepley PetscFunctionBegin; 1951c5929fdfSBarry Smith ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr); 19521878804aSMatthew G. Knepley if (!check) PetscFunctionReturn(0); 19531878804aSMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 19541878804aSMatthew G. Knepley ierr = VecDuplicate(u, &sol);CHKERRQ(ierr); 19551878804aSMatthew G. Knepley ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr); 19567f96f943SMatthew G. Knepley ierr = DMSNESCheck_Internal(snes, dm, sol);CHKERRQ(ierr); 19571878804aSMatthew G. Knepley ierr = VecDestroy(&sol);CHKERRQ(ierr); 1958552f7358SJed Brown PetscFunctionReturn(0); 1959552f7358SJed Brown } 1960