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> 4af0996ceSBarry Smith #include <petsc/private/petscimpl.h> 5af0996ceSBarry Smith #include <petsc/private/petscfeimpl.h> 6552f7358SJed Brown 7649ef022SMatthew Knepley static void pressure_Private(PetscInt dim, PetscInt Nf, PetscInt NfAux, 8649ef022SMatthew Knepley const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 9649ef022SMatthew Knepley const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 10649ef022SMatthew Knepley PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar p[]) 11649ef022SMatthew Knepley { 12649ef022SMatthew Knepley p[0] = u[uOff[1]]; 13649ef022SMatthew Knepley } 14649ef022SMatthew Knepley 15649ef022SMatthew Knepley /* 16649ef022SMatthew 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. 17649ef022SMatthew Knepley 18649ef022SMatthew Knepley Collective on SNES 19649ef022SMatthew Knepley 20649ef022SMatthew Knepley Input Parameters: 21649ef022SMatthew Knepley + snes - The SNES 22649ef022SMatthew Knepley . pfield - The field number for pressure 23649ef022SMatthew Knepley . nullspace - The pressure nullspace 24649ef022SMatthew Knepley . u - The solution vector 25649ef022SMatthew Knepley - ctx - An optional user context 26649ef022SMatthew Knepley 27649ef022SMatthew Knepley Output Parameter: 28649ef022SMatthew Knepley . u - The solution with a continuum pressure integral of zero 29649ef022SMatthew Knepley 30649ef022SMatthew Knepley Notes: 31649ef022SMatthew 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. 32649ef022SMatthew Knepley 33649ef022SMatthew Knepley Level: developer 34649ef022SMatthew Knepley 35649ef022SMatthew Knepley .seealso: SNESConvergedCorrectPressure() 36649ef022SMatthew Knepley */ 37649ef022SMatthew Knepley static PetscErrorCode SNESCorrectDiscretePressure_Private(SNES snes, PetscInt pfield, MatNullSpace nullspace, Vec u, void *ctx) 38649ef022SMatthew Knepley { 39649ef022SMatthew Knepley DM dm; 40649ef022SMatthew Knepley PetscDS ds; 41649ef022SMatthew Knepley const Vec *nullvecs; 42649ef022SMatthew Knepley PetscScalar pintd, *intc, *intn; 43649ef022SMatthew Knepley MPI_Comm comm; 44649ef022SMatthew Knepley PetscInt Nf, Nv; 45649ef022SMatthew Knepley PetscErrorCode ierr; 46649ef022SMatthew Knepley 47649ef022SMatthew Knepley PetscFunctionBegin; 48649ef022SMatthew Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 49649ef022SMatthew Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 502c71b3e2SJacob Faibussowitsch PetscCheckFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a SNES DM"); 512c71b3e2SJacob Faibussowitsch PetscCheckFalse(!nullspace,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a Jacobian nullspace"); 52649ef022SMatthew Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 53649ef022SMatthew Knepley ierr = PetscDSSetObjective(ds, pfield, pressure_Private);CHKERRQ(ierr); 54649ef022SMatthew Knepley ierr = MatNullSpaceGetVecs(nullspace, NULL, &Nv, &nullvecs);CHKERRQ(ierr); 552c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nv != 1,comm, PETSC_ERR_ARG_OUTOFRANGE, "Can only handle a single null vector for pressure, not %D", Nv); 56649ef022SMatthew Knepley ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr); 572c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(pintd) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Discrete integral of pressure: %g", (double) PetscRealPart(pintd)); 58649ef022SMatthew Knepley ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 59649ef022SMatthew Knepley ierr = PetscMalloc2(Nf, &intc, Nf, &intn);CHKERRQ(ierr); 60649ef022SMatthew Knepley ierr = DMPlexComputeIntegralFEM(dm, nullvecs[0], intn, ctx);CHKERRQ(ierr); 61649ef022SMatthew Knepley ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr); 62649ef022SMatthew Knepley ierr = VecAXPY(u, -intc[pfield]/intn[pfield], nullvecs[0]);CHKERRQ(ierr); 63649ef022SMatthew Knepley #if defined (PETSC_USE_DEBUG) 64649ef022SMatthew Knepley ierr = DMPlexComputeIntegralFEM(dm, u, intc, ctx);CHKERRQ(ierr); 652c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(intc[pfield]) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Continuum integral of pressure after correction: %g", (double) PetscRealPart(intc[pfield])); 66649ef022SMatthew Knepley #endif 67649ef022SMatthew Knepley ierr = PetscFree2(intc, intn);CHKERRQ(ierr); 68649ef022SMatthew Knepley PetscFunctionReturn(0); 69649ef022SMatthew Knepley } 70649ef022SMatthew Knepley 71649ef022SMatthew Knepley /*@C 72649ef022SMatthew 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(). 73649ef022SMatthew Knepley 74649ef022SMatthew Knepley Logically Collective on SNES 75649ef022SMatthew Knepley 76649ef022SMatthew Knepley Input Parameters: 77649ef022SMatthew Knepley + snes - the SNES context 78649ef022SMatthew Knepley . it - the iteration (0 indicates before any Newton steps) 79649ef022SMatthew Knepley . xnorm - 2-norm of current iterate 80649ef022SMatthew Knepley . snorm - 2-norm of current step 81649ef022SMatthew Knepley . fnorm - 2-norm of function at current iterate 82649ef022SMatthew Knepley - ctx - Optional user context 83649ef022SMatthew Knepley 84649ef022SMatthew Knepley Output Parameter: 85649ef022SMatthew Knepley . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 86649ef022SMatthew Knepley 87649ef022SMatthew Knepley Notes: 88649ef022SMatthew 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. 89649ef022SMatthew Knepley 90649ef022SMatthew Knepley Level: advanced 91649ef022SMatthew Knepley 92649ef022SMatthew Knepley .seealso: SNESConvergedDefault(), SNESSetConvergenceTest(), DMSetNullSpaceConstructor() 93649ef022SMatthew Knepley @*/ 94649ef022SMatthew Knepley PetscErrorCode SNESConvergedCorrectPressure(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *ctx) 95649ef022SMatthew Knepley { 96649ef022SMatthew Knepley PetscBool monitorIntegral = PETSC_FALSE; 97649ef022SMatthew Knepley PetscErrorCode ierr; 98649ef022SMatthew Knepley 99649ef022SMatthew Knepley PetscFunctionBegin; 100649ef022SMatthew Knepley ierr = SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx);CHKERRQ(ierr); 101649ef022SMatthew Knepley if (monitorIntegral) { 102649ef022SMatthew Knepley Mat J; 103649ef022SMatthew Knepley Vec u; 104649ef022SMatthew Knepley MatNullSpace nullspace; 105649ef022SMatthew Knepley const Vec *nullvecs; 106649ef022SMatthew Knepley PetscScalar pintd; 107649ef022SMatthew Knepley 108649ef022SMatthew Knepley ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); 109649ef022SMatthew Knepley ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr); 110649ef022SMatthew Knepley ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr); 111649ef022SMatthew Knepley ierr = MatNullSpaceGetVecs(nullspace, NULL, NULL, &nullvecs);CHKERRQ(ierr); 112649ef022SMatthew Knepley ierr = VecDot(nullvecs[0], u, &pintd);CHKERRQ(ierr); 1137d3de750SJacob Faibussowitsch ierr = PetscInfo(snes, "SNES: Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd));CHKERRQ(ierr); 114649ef022SMatthew Knepley } 115649ef022SMatthew Knepley if (*reason > 0) { 116649ef022SMatthew Knepley Mat J; 117649ef022SMatthew Knepley Vec u; 118649ef022SMatthew Knepley MatNullSpace nullspace; 119649ef022SMatthew Knepley PetscInt pfield = 1; 120649ef022SMatthew Knepley 121649ef022SMatthew Knepley ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); 122649ef022SMatthew Knepley ierr = SNESGetJacobian(snes, &J, NULL, NULL, NULL);CHKERRQ(ierr); 123649ef022SMatthew Knepley ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr); 124649ef022SMatthew Knepley ierr = SNESCorrectDiscretePressure_Private(snes, pfield, nullspace, u, ctx);CHKERRQ(ierr); 125649ef022SMatthew Knepley } 126649ef022SMatthew Knepley PetscFunctionReturn(0); 127649ef022SMatthew Knepley } 128649ef022SMatthew Knepley 12924cdb843SMatthew G. Knepley /************************** Interpolation *******************************/ 13024cdb843SMatthew G. Knepley 1316da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy) 1326da023fcSToby Isaac { 1336da023fcSToby Isaac PetscBool isPlex; 1346da023fcSToby Isaac PetscErrorCode ierr; 1356da023fcSToby Isaac 1366da023fcSToby Isaac PetscFunctionBegin; 1376da023fcSToby Isaac ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr); 1386da023fcSToby Isaac if (isPlex) { 1396da023fcSToby Isaac *plex = dm; 1406da023fcSToby Isaac ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 141f7148743SMatthew G. Knepley } else { 142f7148743SMatthew G. Knepley ierr = PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex);CHKERRQ(ierr); 143f7148743SMatthew G. Knepley if (!*plex) { 1446da023fcSToby Isaac ierr = DMConvert(dm,DMPLEX,plex);CHKERRQ(ierr); 145f7148743SMatthew G. Knepley ierr = PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex);CHKERRQ(ierr); 1466da023fcSToby Isaac if (copy) { 1476da023fcSToby Isaac ierr = DMCopyDMSNES(dm, *plex);CHKERRQ(ierr); 1489a2a23afSMatthew G. Knepley ierr = DMCopyAuxiliaryVec(dm, *plex);CHKERRQ(ierr); 1496da023fcSToby Isaac } 150f7148743SMatthew G. Knepley } else { 151f7148743SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) *plex);CHKERRQ(ierr); 152f7148743SMatthew G. Knepley } 1536da023fcSToby Isaac } 1546da023fcSToby Isaac PetscFunctionReturn(0); 1556da023fcSToby Isaac } 1566da023fcSToby Isaac 1574267b1a3SMatthew G. Knepley /*@C 1584267b1a3SMatthew G. Knepley DMInterpolationCreate - Creates a DMInterpolationInfo context 1594267b1a3SMatthew G. Knepley 160d083f849SBarry Smith Collective 1614267b1a3SMatthew G. Knepley 1624267b1a3SMatthew G. Knepley Input Parameter: 1634267b1a3SMatthew G. Knepley . comm - the communicator 1644267b1a3SMatthew G. Knepley 1654267b1a3SMatthew G. Knepley Output Parameter: 1664267b1a3SMatthew G. Knepley . ctx - the context 1674267b1a3SMatthew G. Knepley 1684267b1a3SMatthew G. Knepley Level: beginner 1694267b1a3SMatthew G. Knepley 1704267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationDestroy() 1714267b1a3SMatthew G. Knepley @*/ 1720adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx) 1730adebc6cSBarry Smith { 174552f7358SJed Brown PetscErrorCode ierr; 175552f7358SJed Brown 176552f7358SJed Brown PetscFunctionBegin; 177552f7358SJed Brown PetscValidPointer(ctx, 2); 17895dccacaSBarry Smith ierr = PetscNew(ctx);CHKERRQ(ierr); 1791aa26658SKarl Rupp 180552f7358SJed Brown (*ctx)->comm = comm; 181552f7358SJed Brown (*ctx)->dim = -1; 182552f7358SJed Brown (*ctx)->nInput = 0; 1830298fd71SBarry Smith (*ctx)->points = NULL; 1840298fd71SBarry Smith (*ctx)->cells = NULL; 185552f7358SJed Brown (*ctx)->n = -1; 1860298fd71SBarry Smith (*ctx)->coords = NULL; 187552f7358SJed Brown PetscFunctionReturn(0); 188552f7358SJed Brown } 189552f7358SJed Brown 1904267b1a3SMatthew G. Knepley /*@C 1914267b1a3SMatthew G. Knepley DMInterpolationSetDim - Sets the spatial dimension for the interpolation context 1924267b1a3SMatthew G. Knepley 1934267b1a3SMatthew G. Knepley Not collective 1944267b1a3SMatthew G. Knepley 1954267b1a3SMatthew G. Knepley Input Parameters: 1964267b1a3SMatthew G. Knepley + ctx - the context 1974267b1a3SMatthew G. Knepley - dim - the spatial dimension 1984267b1a3SMatthew G. Knepley 1994267b1a3SMatthew G. Knepley Level: intermediate 2004267b1a3SMatthew G. Knepley 2014267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2024267b1a3SMatthew G. Knepley @*/ 2030adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim) 2040adebc6cSBarry Smith { 205552f7358SJed Brown PetscFunctionBegin; 2062c71b3e2SJacob Faibussowitsch PetscCheckFalse((dim < 1) || (dim > 3),ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %D", dim); 207552f7358SJed Brown ctx->dim = dim; 208552f7358SJed Brown PetscFunctionReturn(0); 209552f7358SJed Brown } 210552f7358SJed Brown 2114267b1a3SMatthew G. Knepley /*@C 2124267b1a3SMatthew G. Knepley DMInterpolationGetDim - Gets the spatial dimension for the interpolation context 2134267b1a3SMatthew G. Knepley 2144267b1a3SMatthew G. Knepley Not collective 2154267b1a3SMatthew G. Knepley 2164267b1a3SMatthew G. Knepley Input Parameter: 2174267b1a3SMatthew G. Knepley . ctx - the context 2184267b1a3SMatthew G. Knepley 2194267b1a3SMatthew G. Knepley Output Parameter: 2204267b1a3SMatthew G. Knepley . dim - the spatial dimension 2214267b1a3SMatthew G. Knepley 2224267b1a3SMatthew G. Knepley Level: intermediate 2234267b1a3SMatthew G. Knepley 2244267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2254267b1a3SMatthew G. Knepley @*/ 2260adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim) 2270adebc6cSBarry Smith { 228552f7358SJed Brown PetscFunctionBegin; 229552f7358SJed Brown PetscValidIntPointer(dim, 2); 230552f7358SJed Brown *dim = ctx->dim; 231552f7358SJed Brown PetscFunctionReturn(0); 232552f7358SJed Brown } 233552f7358SJed Brown 2344267b1a3SMatthew G. Knepley /*@C 2354267b1a3SMatthew G. Knepley DMInterpolationSetDof - Sets the number of fields interpolated at a point for the interpolation context 2364267b1a3SMatthew G. Knepley 2374267b1a3SMatthew G. Knepley Not collective 2384267b1a3SMatthew G. Knepley 2394267b1a3SMatthew G. Knepley Input Parameters: 2404267b1a3SMatthew G. Knepley + ctx - the context 2414267b1a3SMatthew G. Knepley - dof - the number of fields 2424267b1a3SMatthew G. Knepley 2434267b1a3SMatthew G. Knepley Level: intermediate 2444267b1a3SMatthew G. Knepley 2454267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2464267b1a3SMatthew G. Knepley @*/ 2470adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof) 2480adebc6cSBarry Smith { 249552f7358SJed Brown PetscFunctionBegin; 2502c71b3e2SJacob Faibussowitsch PetscCheckFalse(dof < 1,ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %D", dof); 251552f7358SJed Brown ctx->dof = dof; 252552f7358SJed Brown PetscFunctionReturn(0); 253552f7358SJed Brown } 254552f7358SJed Brown 2554267b1a3SMatthew G. Knepley /*@C 2564267b1a3SMatthew G. Knepley DMInterpolationGetDof - Gets the number of fields interpolated at a point for the interpolation context 2574267b1a3SMatthew G. Knepley 2584267b1a3SMatthew G. Knepley Not collective 2594267b1a3SMatthew G. Knepley 2604267b1a3SMatthew G. Knepley Input Parameter: 2614267b1a3SMatthew G. Knepley . ctx - the context 2624267b1a3SMatthew G. Knepley 2634267b1a3SMatthew G. Knepley Output Parameter: 2644267b1a3SMatthew G. Knepley . dof - the number of fields 2654267b1a3SMatthew G. Knepley 2664267b1a3SMatthew G. Knepley Level: intermediate 2674267b1a3SMatthew G. Knepley 2684267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2694267b1a3SMatthew G. Knepley @*/ 2700adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof) 2710adebc6cSBarry Smith { 272552f7358SJed Brown PetscFunctionBegin; 273552f7358SJed Brown PetscValidIntPointer(dof, 2); 274552f7358SJed Brown *dof = ctx->dof; 275552f7358SJed Brown PetscFunctionReturn(0); 276552f7358SJed Brown } 277552f7358SJed Brown 2784267b1a3SMatthew G. Knepley /*@C 2794267b1a3SMatthew G. Knepley DMInterpolationAddPoints - Add points at which we will interpolate the fields 2804267b1a3SMatthew G. Knepley 2814267b1a3SMatthew G. Knepley Not collective 2824267b1a3SMatthew G. Knepley 2834267b1a3SMatthew G. Knepley Input Parameters: 2844267b1a3SMatthew G. Knepley + ctx - the context 2854267b1a3SMatthew G. Knepley . n - the number of points 2864267b1a3SMatthew G. Knepley - points - the coordinates for each point, an array of size n * dim 2874267b1a3SMatthew G. Knepley 2884267b1a3SMatthew G. Knepley Note: The coordinate information is copied. 2894267b1a3SMatthew G. Knepley 2904267b1a3SMatthew G. Knepley Level: intermediate 2914267b1a3SMatthew G. Knepley 2924267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationCreate() 2934267b1a3SMatthew G. Knepley @*/ 2940adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[]) 2950adebc6cSBarry Smith { 296552f7358SJed Brown PetscErrorCode ierr; 297552f7358SJed Brown 298552f7358SJed Brown PetscFunctionBegin; 2992c71b3e2SJacob Faibussowitsch PetscCheckFalse(ctx->dim < 0,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 3002c71b3e2SJacob Faibussowitsch PetscCheckFalse(ctx->points,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet"); 301552f7358SJed Brown ctx->nInput = n; 3021aa26658SKarl Rupp 303785e854fSJed Brown ierr = PetscMalloc1(n*ctx->dim, &ctx->points);CHKERRQ(ierr); 304580bdb30SBarry Smith ierr = PetscArraycpy(ctx->points, points, n*ctx->dim);CHKERRQ(ierr); 305552f7358SJed Brown PetscFunctionReturn(0); 306552f7358SJed Brown } 307552f7358SJed Brown 3084267b1a3SMatthew G. Knepley /*@C 30952aa1562SMatthew G. Knepley DMInterpolationSetUp - Compute spatial indices for point location during interpolation 3104267b1a3SMatthew G. Knepley 3114267b1a3SMatthew G. Knepley Collective on ctx 3124267b1a3SMatthew G. Knepley 3134267b1a3SMatthew G. Knepley Input Parameters: 3144267b1a3SMatthew G. Knepley + ctx - the context 3154267b1a3SMatthew G. Knepley . dm - the DM for the function space used for interpolation 31652aa1562SMatthew G. Knepley . redundantPoints - If PETSC_TRUE, all processes are passing in the same array of points. Otherwise, points need to be communicated among processes. 3177deeda50SSatish Balay - ignoreOutsideDomain - If PETSC_TRUE, ignore points outside the domain, otherwise return an error 3184267b1a3SMatthew G. Knepley 3194267b1a3SMatthew G. Knepley Level: intermediate 3204267b1a3SMatthew G. Knepley 3214267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 3224267b1a3SMatthew G. Knepley @*/ 32352aa1562SMatthew G. Knepley PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints, PetscBool ignoreOutsideDomain) 3240adebc6cSBarry Smith { 325552f7358SJed Brown MPI_Comm comm = ctx->comm; 326552f7358SJed Brown PetscScalar *a; 327552f7358SJed Brown PetscInt p, q, i; 328552f7358SJed Brown PetscMPIInt rank, size; 329552f7358SJed Brown PetscErrorCode ierr; 330552f7358SJed Brown Vec pointVec; 3313a93e3b7SToby Isaac PetscSF cellSF; 332552f7358SJed Brown PetscLayout layout; 333552f7358SJed Brown PetscReal *globalPoints; 334cb313848SJed Brown PetscScalar *globalPointsScalar; 335552f7358SJed Brown const PetscInt *ranges; 336552f7358SJed Brown PetscMPIInt *counts, *displs; 3373a93e3b7SToby Isaac const PetscSFNode *foundCells; 3383a93e3b7SToby Isaac const PetscInt *foundPoints; 339552f7358SJed Brown PetscMPIInt *foundProcs, *globalProcs; 3403a93e3b7SToby Isaac PetscInt n, N, numFound; 341552f7358SJed Brown 34219436ca2SJed Brown PetscFunctionBegin; 343064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 344ffc4695bSBarry Smith ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 345ffc4695bSBarry Smith ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 3462c71b3e2SJacob Faibussowitsch PetscCheckFalse(ctx->dim < 0,comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 34719436ca2SJed Brown /* Locate points */ 34819436ca2SJed Brown n = ctx->nInput; 349552f7358SJed Brown if (!redundantPoints) { 350552f7358SJed Brown ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 351552f7358SJed Brown ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 352552f7358SJed Brown ierr = PetscLayoutSetLocalSize(layout, n);CHKERRQ(ierr); 353552f7358SJed Brown ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 354552f7358SJed Brown ierr = PetscLayoutGetSize(layout, &N);CHKERRQ(ierr); 355552f7358SJed Brown /* Communicate all points to all processes */ 356dcca6d9dSJed Brown ierr = PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs);CHKERRQ(ierr); 357552f7358SJed Brown ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 358552f7358SJed Brown for (p = 0; p < size; ++p) { 359552f7358SJed Brown counts[p] = (ranges[p+1] - ranges[p])*ctx->dim; 360552f7358SJed Brown displs[p] = ranges[p]*ctx->dim; 361552f7358SJed Brown } 362ffc4695bSBarry Smith ierr = MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm);CHKERRMPI(ierr); 363552f7358SJed Brown } else { 364552f7358SJed Brown N = n; 365552f7358SJed Brown globalPoints = ctx->points; 36638ea73c8SJed Brown counts = displs = NULL; 36738ea73c8SJed Brown layout = NULL; 368552f7358SJed Brown } 369552f7358SJed Brown #if 0 370dcca6d9dSJed Brown ierr = PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs);CHKERRQ(ierr); 37119436ca2SJed Brown /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */ 372552f7358SJed Brown #else 373cb313848SJed Brown #if defined(PETSC_USE_COMPLEX) 37446b3086cSToby Isaac ierr = PetscMalloc1(N*ctx->dim,&globalPointsScalar);CHKERRQ(ierr); 37546b3086cSToby Isaac for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i]; 376cb313848SJed Brown #else 377cb313848SJed Brown globalPointsScalar = globalPoints; 378cb313848SJed Brown #endif 37904706141SMatthew G Knepley ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec);CHKERRQ(ierr); 380dcca6d9dSJed Brown ierr = PetscMalloc2(N,&foundProcs,N,&globalProcs);CHKERRQ(ierr); 3817b5f2079SMatthew G. Knepley for (p = 0; p < N; ++p) {foundProcs[p] = size;} 3823a93e3b7SToby Isaac cellSF = NULL; 3832d1fa6caSMatthew G. Knepley ierr = DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF);CHKERRQ(ierr); 3843a93e3b7SToby Isaac ierr = PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells);CHKERRQ(ierr); 385552f7358SJed Brown #endif 3863a93e3b7SToby Isaac for (p = 0; p < numFound; ++p) { 3873a93e3b7SToby Isaac if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank; 388552f7358SJed Brown } 389552f7358SJed Brown /* Let the lowest rank process own each point */ 390820f2d46SBarry Smith ierr = MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm);CHKERRMPI(ierr); 391552f7358SJed Brown ctx->n = 0; 392552f7358SJed Brown for (p = 0; p < N; ++p) { 39352aa1562SMatthew G. Knepley if (globalProcs[p] == size) { 3942c71b3e2SJacob Faibussowitsch PetscCheckFalse(!ignoreOutsideDomain,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)); 395dd400576SPatrick Sanan else if (rank == 0) ++ctx->n; 39652aa1562SMatthew G. Knepley } else if (globalProcs[p] == rank) ++ctx->n; 397552f7358SJed Brown } 398552f7358SJed Brown /* Create coordinates vector and array of owned cells */ 399785e854fSJed Brown ierr = PetscMalloc1(ctx->n, &ctx->cells);CHKERRQ(ierr); 400552f7358SJed Brown ierr = VecCreate(comm, &ctx->coords);CHKERRQ(ierr); 401552f7358SJed Brown ierr = VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE);CHKERRQ(ierr); 402552f7358SJed Brown ierr = VecSetBlockSize(ctx->coords, ctx->dim);CHKERRQ(ierr); 403c0dedaeaSBarry Smith ierr = VecSetType(ctx->coords,VECSTANDARD);CHKERRQ(ierr); 404552f7358SJed Brown ierr = VecGetArray(ctx->coords, &a);CHKERRQ(ierr); 405552f7358SJed Brown for (p = 0, q = 0, i = 0; p < N; ++p) { 406552f7358SJed Brown if (globalProcs[p] == rank) { 407552f7358SJed Brown PetscInt d; 408552f7358SJed Brown 4091aa26658SKarl Rupp for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d]; 410f317b747SMatthew G. Knepley ctx->cells[q] = foundCells[q].index; 411f317b747SMatthew G. Knepley ++q; 412552f7358SJed Brown } 413dd400576SPatrick Sanan if (globalProcs[p] == size && rank == 0) { 41452aa1562SMatthew G. Knepley PetscInt d; 41552aa1562SMatthew G. Knepley 41652aa1562SMatthew G. Knepley for (d = 0; d < ctx->dim; ++d, ++i) a[i] = 0.; 41752aa1562SMatthew G. Knepley ctx->cells[q] = -1; 41852aa1562SMatthew G. Knepley ++q; 41952aa1562SMatthew G. Knepley } 420552f7358SJed Brown } 421552f7358SJed Brown ierr = VecRestoreArray(ctx->coords, &a);CHKERRQ(ierr); 422552f7358SJed Brown #if 0 423552f7358SJed Brown ierr = PetscFree3(foundCells,foundProcs,globalProcs);CHKERRQ(ierr); 424552f7358SJed Brown #else 425552f7358SJed Brown ierr = PetscFree2(foundProcs,globalProcs);CHKERRQ(ierr); 4263a93e3b7SToby Isaac ierr = PetscSFDestroy(&cellSF);CHKERRQ(ierr); 427552f7358SJed Brown ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 428552f7358SJed Brown #endif 429cb313848SJed Brown if ((void*)globalPointsScalar != (void*)globalPoints) {ierr = PetscFree(globalPointsScalar);CHKERRQ(ierr);} 430d343d804SMatthew G. Knepley if (!redundantPoints) {ierr = PetscFree3(globalPoints,counts,displs);CHKERRQ(ierr);} 431552f7358SJed Brown ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 432552f7358SJed Brown PetscFunctionReturn(0); 433552f7358SJed Brown } 434552f7358SJed Brown 4354267b1a3SMatthew G. Knepley /*@C 4364267b1a3SMatthew G. Knepley DMInterpolationGetCoordinates - Gets a Vec with the coordinates of each interpolation point 4374267b1a3SMatthew G. Knepley 4384267b1a3SMatthew G. Knepley Collective on ctx 4394267b1a3SMatthew G. Knepley 4404267b1a3SMatthew G. Knepley Input Parameter: 4414267b1a3SMatthew G. Knepley . ctx - the context 4424267b1a3SMatthew G. Knepley 4434267b1a3SMatthew G. Knepley Output Parameter: 4444267b1a3SMatthew G. Knepley . coordinates - the coordinates of interpolation points 4454267b1a3SMatthew G. Knepley 4464267b1a3SMatthew 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. 4474267b1a3SMatthew G. Knepley 4484267b1a3SMatthew G. Knepley Level: intermediate 4494267b1a3SMatthew G. Knepley 4504267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 4514267b1a3SMatthew G. Knepley @*/ 4520adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates) 4530adebc6cSBarry Smith { 454552f7358SJed Brown PetscFunctionBegin; 455552f7358SJed Brown PetscValidPointer(coordinates, 2); 4562c71b3e2SJacob Faibussowitsch PetscCheckFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 457552f7358SJed Brown *coordinates = ctx->coords; 458552f7358SJed Brown PetscFunctionReturn(0); 459552f7358SJed Brown } 460552f7358SJed Brown 4614267b1a3SMatthew G. Knepley /*@C 4624267b1a3SMatthew G. Knepley DMInterpolationGetVector - Gets a Vec which can hold all the interpolated field values 4634267b1a3SMatthew G. Knepley 4644267b1a3SMatthew G. Knepley Collective on ctx 4654267b1a3SMatthew G. Knepley 4664267b1a3SMatthew G. Knepley Input Parameter: 4674267b1a3SMatthew G. Knepley . ctx - the context 4684267b1a3SMatthew G. Knepley 4694267b1a3SMatthew G. Knepley Output Parameter: 4704267b1a3SMatthew G. Knepley . v - a vector capable of holding the interpolated field values 4714267b1a3SMatthew G. Knepley 4724267b1a3SMatthew G. Knepley Note: This vector should be returned using DMInterpolationRestoreVector(). 4734267b1a3SMatthew G. Knepley 4744267b1a3SMatthew G. Knepley Level: intermediate 4754267b1a3SMatthew G. Knepley 4764267b1a3SMatthew G. Knepley .seealso: DMInterpolationRestoreVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 4774267b1a3SMatthew G. Knepley @*/ 4780adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v) 4790adebc6cSBarry Smith { 480552f7358SJed Brown PetscErrorCode ierr; 481552f7358SJed Brown 482552f7358SJed Brown PetscFunctionBegin; 483552f7358SJed Brown PetscValidPointer(v, 2); 4842c71b3e2SJacob Faibussowitsch PetscCheckFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 485552f7358SJed Brown ierr = VecCreate(ctx->comm, v);CHKERRQ(ierr); 486552f7358SJed Brown ierr = VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE);CHKERRQ(ierr); 487552f7358SJed Brown ierr = VecSetBlockSize(*v, ctx->dof);CHKERRQ(ierr); 488c0dedaeaSBarry Smith ierr = VecSetType(*v,VECSTANDARD);CHKERRQ(ierr); 489552f7358SJed Brown PetscFunctionReturn(0); 490552f7358SJed Brown } 491552f7358SJed Brown 4924267b1a3SMatthew G. Knepley /*@C 4934267b1a3SMatthew G. Knepley DMInterpolationRestoreVector - Returns a Vec which can hold all the interpolated field values 4944267b1a3SMatthew G. Knepley 4954267b1a3SMatthew G. Knepley Collective on ctx 4964267b1a3SMatthew G. Knepley 4974267b1a3SMatthew G. Knepley Input Parameters: 4984267b1a3SMatthew G. Knepley + ctx - the context 4994267b1a3SMatthew G. Knepley - v - a vector capable of holding the interpolated field values 5004267b1a3SMatthew G. Knepley 5014267b1a3SMatthew G. Knepley Level: intermediate 5024267b1a3SMatthew G. Knepley 5034267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 5044267b1a3SMatthew G. Knepley @*/ 5050adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v) 5060adebc6cSBarry Smith { 507552f7358SJed Brown PetscErrorCode ierr; 508552f7358SJed Brown 509552f7358SJed Brown PetscFunctionBegin; 510552f7358SJed Brown PetscValidPointer(v, 2); 5112c71b3e2SJacob Faibussowitsch PetscCheckFalse(!ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 512552f7358SJed Brown ierr = VecDestroy(v);CHKERRQ(ierr); 513552f7358SJed Brown PetscFunctionReturn(0); 514552f7358SJed Brown } 515552f7358SJed Brown 516*cfe5744fSMatthew G. Knepley static inline PetscErrorCode DMInterpolate_Segment_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 517*cfe5744fSMatthew G. Knepley { 518*cfe5744fSMatthew G. Knepley PetscReal v0, J, invJ, detJ; 519*cfe5744fSMatthew G. Knepley const PetscInt dof = ctx->dof; 520*cfe5744fSMatthew G. Knepley const PetscScalar *coords; 521*cfe5744fSMatthew G. Knepley PetscScalar *a; 522*cfe5744fSMatthew G. Knepley PetscInt p; 523*cfe5744fSMatthew G. Knepley PetscErrorCode ierr; 524*cfe5744fSMatthew G. Knepley 525*cfe5744fSMatthew G. Knepley PetscFunctionBegin; 526*cfe5744fSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 527*cfe5744fSMatthew G. Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 528*cfe5744fSMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 529*cfe5744fSMatthew G. Knepley PetscInt c = ctx->cells[p]; 530*cfe5744fSMatthew G. Knepley PetscScalar *x = NULL; 531*cfe5744fSMatthew G. Knepley PetscReal xir[1]; 532*cfe5744fSMatthew G. Knepley PetscInt xSize, comp; 533*cfe5744fSMatthew G. Knepley 534*cfe5744fSMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0, &J, &invJ, &detJ);CHKERRQ(ierr); 535*cfe5744fSMatthew G. Knepley PetscCheck(detJ > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT, (double) detJ, c); 536*cfe5744fSMatthew G. Knepley xir[0] = invJ*PetscRealPart(coords[p] - v0); 537*cfe5744fSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 538*cfe5744fSMatthew G. Knepley if (2*dof == xSize) { 539*cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp]*(1 - xir[0]) + x[1*dof+comp]*xir[0]; 540*cfe5744fSMatthew G. Knepley } else if (dof == xSize) { 541*cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp]; 542*cfe5744fSMatthew G. Knepley } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input closure size %" PetscInt_FMT " must be either %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 2*dof, dof); 543*cfe5744fSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 544*cfe5744fSMatthew G. Knepley } 545*cfe5744fSMatthew G. Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 546*cfe5744fSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 547*cfe5744fSMatthew G. Knepley PetscFunctionReturn(0); 548*cfe5744fSMatthew G. Knepley } 549*cfe5744fSMatthew G. Knepley 5509fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 551a6dfd86eSKarl Rupp { 552552f7358SJed Brown PetscReal *v0, *J, *invJ, detJ; 55356044e6dSMatthew G. Knepley const PetscScalar *coords; 55456044e6dSMatthew G. Knepley PetscScalar *a; 555552f7358SJed Brown PetscInt p; 556552f7358SJed Brown PetscErrorCode ierr; 557552f7358SJed Brown 558552f7358SJed Brown PetscFunctionBegin; 559dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 56056044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 561552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 562552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 563552f7358SJed Brown PetscInt c = ctx->cells[p]; 564a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 565552f7358SJed Brown PetscReal xi[4]; 566552f7358SJed Brown PetscInt d, f, comp; 567552f7358SJed Brown 5688e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 5692c71b3e2SJacob Faibussowitsch PetscCheckFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 5700298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 5711aa26658SKarl Rupp for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 5721aa26658SKarl Rupp 573552f7358SJed Brown for (d = 0; d < ctx->dim; ++d) { 574552f7358SJed Brown xi[d] = 0.0; 5751aa26658SKarl 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]); 5761aa26658SKarl 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]; 577552f7358SJed Brown } 5780298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 579552f7358SJed Brown } 580552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 58156044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 582552f7358SJed Brown ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 583552f7358SJed Brown PetscFunctionReturn(0); 584552f7358SJed Brown } 585552f7358SJed Brown 5869fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 5877a1931ceSMatthew G. Knepley { 5887a1931ceSMatthew G. Knepley PetscReal *v0, *J, *invJ, detJ; 58956044e6dSMatthew G. Knepley const PetscScalar *coords; 59056044e6dSMatthew G. Knepley PetscScalar *a; 5917a1931ceSMatthew G. Knepley PetscInt p; 5927a1931ceSMatthew G. Knepley PetscErrorCode ierr; 5937a1931ceSMatthew G. Knepley 5947a1931ceSMatthew G. Knepley PetscFunctionBegin; 595dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 59656044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 5977a1931ceSMatthew G. Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 5987a1931ceSMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 5997a1931ceSMatthew G. Knepley PetscInt c = ctx->cells[p]; 6007a1931ceSMatthew G. Knepley const PetscInt order[3] = {2, 1, 3}; 6012584bbe8SMatthew G. Knepley PetscScalar *x = NULL; 6027a1931ceSMatthew G. Knepley PetscReal xi[4]; 6037a1931ceSMatthew G. Knepley PetscInt d, f, comp; 6047a1931ceSMatthew G. Knepley 6058e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 6062c71b3e2SJacob Faibussowitsch PetscCheckFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 6077a1931ceSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 6087a1931ceSMatthew G. Knepley for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 6097a1931ceSMatthew G. Knepley 6107a1931ceSMatthew G. Knepley for (d = 0; d < ctx->dim; ++d) { 6117a1931ceSMatthew G. Knepley xi[d] = 0.0; 6127a1931ceSMatthew 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]); 6137a1931ceSMatthew 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]; 6147a1931ceSMatthew G. Knepley } 6157a1931ceSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 6167a1931ceSMatthew G. Knepley } 6177a1931ceSMatthew G. Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 61856044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 6197a1931ceSMatthew G. Knepley ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 6207a1931ceSMatthew G. Knepley PetscFunctionReturn(0); 6217a1931ceSMatthew G. Knepley } 6227a1931ceSMatthew G. Knepley 6239fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 624552f7358SJed Brown { 625552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 626552f7358SJed Brown const PetscScalar x0 = vertices[0]; 627552f7358SJed Brown const PetscScalar y0 = vertices[1]; 628552f7358SJed Brown const PetscScalar x1 = vertices[2]; 629552f7358SJed Brown const PetscScalar y1 = vertices[3]; 630552f7358SJed Brown const PetscScalar x2 = vertices[4]; 631552f7358SJed Brown const PetscScalar y2 = vertices[5]; 632552f7358SJed Brown const PetscScalar x3 = vertices[6]; 633552f7358SJed Brown const PetscScalar y3 = vertices[7]; 634552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 635552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 636552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 637552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 638552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 639552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 64056044e6dSMatthew G. Knepley const PetscScalar *ref; 64156044e6dSMatthew G. Knepley PetscScalar *real; 642552f7358SJed Brown PetscErrorCode ierr; 643552f7358SJed Brown 644552f7358SJed Brown PetscFunctionBegin; 64556044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 646552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 647552f7358SJed Brown { 648552f7358SJed Brown const PetscScalar p0 = ref[0]; 649552f7358SJed Brown const PetscScalar p1 = ref[1]; 650552f7358SJed Brown 651552f7358SJed Brown real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1; 652552f7358SJed Brown real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1; 653552f7358SJed Brown } 654552f7358SJed Brown ierr = PetscLogFlops(28);CHKERRQ(ierr); 65556044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 656552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 657552f7358SJed Brown PetscFunctionReturn(0); 658552f7358SJed Brown } 659552f7358SJed Brown 660af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 6619fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 662552f7358SJed Brown { 663552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 664552f7358SJed Brown const PetscScalar x0 = vertices[0]; 665552f7358SJed Brown const PetscScalar y0 = vertices[1]; 666552f7358SJed Brown const PetscScalar x1 = vertices[2]; 667552f7358SJed Brown const PetscScalar y1 = vertices[3]; 668552f7358SJed Brown const PetscScalar x2 = vertices[4]; 669552f7358SJed Brown const PetscScalar y2 = vertices[5]; 670552f7358SJed Brown const PetscScalar x3 = vertices[6]; 671552f7358SJed Brown const PetscScalar y3 = vertices[7]; 672552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 673552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 67456044e6dSMatthew G. Knepley const PetscScalar *ref; 675552f7358SJed Brown PetscErrorCode ierr; 676552f7358SJed Brown 677552f7358SJed Brown PetscFunctionBegin; 67856044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 679552f7358SJed Brown { 680552f7358SJed Brown const PetscScalar x = ref[0]; 681552f7358SJed Brown const PetscScalar y = ref[1]; 682552f7358SJed Brown const PetscInt rows[2] = {0, 1}; 683da80777bSKarl Rupp PetscScalar values[4]; 684da80777bSKarl Rupp 685da80777bSKarl Rupp values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5; 686da80777bSKarl Rupp values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5; 68794ab13aaSBarry Smith ierr = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr); 688552f7358SJed Brown } 689552f7358SJed Brown ierr = PetscLogFlops(30);CHKERRQ(ierr); 69056044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 69194ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 69294ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 693552f7358SJed Brown PetscFunctionReturn(0); 694552f7358SJed Brown } 695552f7358SJed Brown 6969fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 697a6dfd86eSKarl Rupp { 698fafc0619SMatthew G Knepley DM dmCoord; 699de73a395SMatthew G. Knepley PetscFE fem = NULL; 700552f7358SJed Brown SNES snes; 701552f7358SJed Brown KSP ksp; 702552f7358SJed Brown PC pc; 703552f7358SJed Brown Vec coordsLocal, r, ref, real; 704552f7358SJed Brown Mat J; 705716009bfSMatthew G. Knepley PetscTabulation T = NULL; 70656044e6dSMatthew G. Knepley const PetscScalar *coords; 70756044e6dSMatthew G. Knepley PetscScalar *a; 708716009bfSMatthew G. Knepley PetscReal xir[2] = {0., 0.}; 709de73a395SMatthew G. Knepley PetscInt Nf, p; 7105509d985SMatthew G. Knepley const PetscInt dof = ctx->dof; 711552f7358SJed Brown PetscErrorCode ierr; 712552f7358SJed Brown 713552f7358SJed Brown PetscFunctionBegin; 714de73a395SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 715716009bfSMatthew G. Knepley if (Nf) { 716*cfe5744fSMatthew G. Knepley PetscObject obj; 717*cfe5744fSMatthew G. Knepley PetscClassId id; 718*cfe5744fSMatthew G. Knepley 719*cfe5744fSMatthew G. Knepley ierr = DMGetField(dm, 0, NULL, &obj);CHKERRQ(ierr); 720*cfe5744fSMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 721*cfe5744fSMatthew G. Knepley if (id == PETSCFE_CLASSID) {fem = (PetscFE) obj; ierr = PetscFECreateTabulation(fem, 1, 1, xir, 0, &T);CHKERRQ(ierr);} 722716009bfSMatthew G. Knepley } 723552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 724fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 725552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 726552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr); 727552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 728552f7358SJed Brown ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr); 729c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 730552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 731552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 732552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 733552f7358SJed Brown ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr); 734552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 735552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 7360298fd71SBarry Smith ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr); 7370298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr); 738552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 739552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 740552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 741552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 742552f7358SJed Brown 74356044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 744552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 745552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 746a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 747552f7358SJed Brown PetscScalar *xi; 748552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 749552f7358SJed Brown 750552f7358SJed Brown /* Can make this do all points at once */ 7510298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 7522c71b3e2SJacob Faibussowitsch PetscCheckFalse(4*2 != coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 4*2); 7530298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 7543ec1f749SStefano Zampini ierr = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr); 7553ec1f749SStefano Zampini ierr = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr); 756552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 757552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 758552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 759552f7358SJed Brown ierr = VecRestoreArray(real, &xi);CHKERRQ(ierr); 760552f7358SJed Brown ierr = SNESSolve(snes, real, ref);CHKERRQ(ierr); 761552f7358SJed Brown ierr = VecGetArray(ref, &xi);CHKERRQ(ierr); 762cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 763cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 764*cfe5744fSMatthew G. Knepley if (4*dof == xSize) { 765*cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) 766*cfe5744fSMatthew 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]; 767*cfe5744fSMatthew G. Knepley } else if (dof == xSize) { 768*cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp]; 769*cfe5744fSMatthew G. Knepley } else { 7705509d985SMatthew G. Knepley PetscInt d; 7711aa26658SKarl Rupp 7722c71b3e2SJacob Faibussowitsch PetscCheck(fem, ctx->comm, PETSC_ERR_ARG_WRONG, "Cannot have a higher order interpolant if the discretization is not PetscFE"); 7735509d985SMatthew G. Knepley xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0; 774ef0bb6c7SMatthew G. Knepley ierr = PetscFEComputeTabulation(fem, 1, xir, 0, T);CHKERRQ(ierr); 7755509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) { 7765509d985SMatthew G. Knepley a[p*dof+comp] = 0.0; 7775509d985SMatthew G. Knepley for (d = 0; d < xSize/dof; ++d) { 778ef0bb6c7SMatthew G. Knepley a[p*dof+comp] += x[d*dof+comp]*T->T[0][d*dof+comp]; 7795509d985SMatthew G. Knepley } 7805509d985SMatthew G. Knepley } 7815509d985SMatthew G. Knepley } 782552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 7830298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 7840298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 785552f7358SJed Brown } 786ef0bb6c7SMatthew G. Knepley ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr); 787552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 78856044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 789552f7358SJed Brown 790552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 791552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 792552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 793552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 794552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 795552f7358SJed Brown PetscFunctionReturn(0); 796552f7358SJed Brown } 797552f7358SJed Brown 7989fbee547SJacob Faibussowitsch static inline PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 799552f7358SJed Brown { 800552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 801552f7358SJed Brown const PetscScalar x0 = vertices[0]; 802552f7358SJed Brown const PetscScalar y0 = vertices[1]; 803552f7358SJed Brown const PetscScalar z0 = vertices[2]; 8047a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 8057a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 8067a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 807552f7358SJed Brown const PetscScalar x2 = vertices[6]; 808552f7358SJed Brown const PetscScalar y2 = vertices[7]; 809552f7358SJed Brown const PetscScalar z2 = vertices[8]; 8107a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 8117a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 8127a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 813552f7358SJed Brown const PetscScalar x4 = vertices[12]; 814552f7358SJed Brown const PetscScalar y4 = vertices[13]; 815552f7358SJed Brown const PetscScalar z4 = vertices[14]; 816552f7358SJed Brown const PetscScalar x5 = vertices[15]; 817552f7358SJed Brown const PetscScalar y5 = vertices[16]; 818552f7358SJed Brown const PetscScalar z5 = vertices[17]; 819552f7358SJed Brown const PetscScalar x6 = vertices[18]; 820552f7358SJed Brown const PetscScalar y6 = vertices[19]; 821552f7358SJed Brown const PetscScalar z6 = vertices[20]; 822552f7358SJed Brown const PetscScalar x7 = vertices[21]; 823552f7358SJed Brown const PetscScalar y7 = vertices[22]; 824552f7358SJed Brown const PetscScalar z7 = vertices[23]; 825552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 826552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 827552f7358SJed Brown const PetscScalar h_1 = z1 - z0; 828552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 829552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 830552f7358SJed Brown const PetscScalar h_3 = z3 - z0; 831552f7358SJed Brown const PetscScalar f_4 = x4 - x0; 832552f7358SJed Brown const PetscScalar g_4 = y4 - y0; 833552f7358SJed Brown const PetscScalar h_4 = z4 - z0; 834552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 835552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 836552f7358SJed Brown const PetscScalar h_01 = z2 - z1 - z3 + z0; 837552f7358SJed Brown const PetscScalar f_12 = x7 - x3 - x4 + x0; 838552f7358SJed Brown const PetscScalar g_12 = y7 - y3 - y4 + y0; 839552f7358SJed Brown const PetscScalar h_12 = z7 - z3 - z4 + z0; 840552f7358SJed Brown const PetscScalar f_02 = x5 - x1 - x4 + x0; 841552f7358SJed Brown const PetscScalar g_02 = y5 - y1 - y4 + y0; 842552f7358SJed Brown const PetscScalar h_02 = z5 - z1 - z4 + z0; 843552f7358SJed Brown const PetscScalar f_012 = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 844552f7358SJed Brown const PetscScalar g_012 = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 845552f7358SJed Brown const PetscScalar h_012 = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 84656044e6dSMatthew G. Knepley const PetscScalar *ref; 84756044e6dSMatthew G. Knepley PetscScalar *real; 848552f7358SJed Brown PetscErrorCode ierr; 849552f7358SJed Brown 850552f7358SJed Brown PetscFunctionBegin; 85156044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 852552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 853552f7358SJed Brown { 854552f7358SJed Brown const PetscScalar p0 = ref[0]; 855552f7358SJed Brown const PetscScalar p1 = ref[1]; 856552f7358SJed Brown const PetscScalar p2 = ref[2]; 857552f7358SJed Brown 858552f7358SJed 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; 859552f7358SJed 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; 860552f7358SJed 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; 861552f7358SJed Brown } 862552f7358SJed Brown ierr = PetscLogFlops(114);CHKERRQ(ierr); 86356044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 864552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 865552f7358SJed Brown PetscFunctionReturn(0); 866552f7358SJed Brown } 867552f7358SJed Brown 8689fbee547SJacob Faibussowitsch static inline PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 869552f7358SJed Brown { 870552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 871552f7358SJed Brown const PetscScalar x0 = vertices[0]; 872552f7358SJed Brown const PetscScalar y0 = vertices[1]; 873552f7358SJed Brown const PetscScalar z0 = vertices[2]; 8747a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 8757a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 8767a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 877552f7358SJed Brown const PetscScalar x2 = vertices[6]; 878552f7358SJed Brown const PetscScalar y2 = vertices[7]; 879552f7358SJed Brown const PetscScalar z2 = vertices[8]; 8807a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 8817a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 8827a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 883552f7358SJed Brown const PetscScalar x4 = vertices[12]; 884552f7358SJed Brown const PetscScalar y4 = vertices[13]; 885552f7358SJed Brown const PetscScalar z4 = vertices[14]; 886552f7358SJed Brown const PetscScalar x5 = vertices[15]; 887552f7358SJed Brown const PetscScalar y5 = vertices[16]; 888552f7358SJed Brown const PetscScalar z5 = vertices[17]; 889552f7358SJed Brown const PetscScalar x6 = vertices[18]; 890552f7358SJed Brown const PetscScalar y6 = vertices[19]; 891552f7358SJed Brown const PetscScalar z6 = vertices[20]; 892552f7358SJed Brown const PetscScalar x7 = vertices[21]; 893552f7358SJed Brown const PetscScalar y7 = vertices[22]; 894552f7358SJed Brown const PetscScalar z7 = vertices[23]; 895552f7358SJed Brown const PetscScalar f_xy = x2 - x1 - x3 + x0; 896552f7358SJed Brown const PetscScalar g_xy = y2 - y1 - y3 + y0; 897552f7358SJed Brown const PetscScalar h_xy = z2 - z1 - z3 + z0; 898552f7358SJed Brown const PetscScalar f_yz = x7 - x3 - x4 + x0; 899552f7358SJed Brown const PetscScalar g_yz = y7 - y3 - y4 + y0; 900552f7358SJed Brown const PetscScalar h_yz = z7 - z3 - z4 + z0; 901552f7358SJed Brown const PetscScalar f_xz = x5 - x1 - x4 + x0; 902552f7358SJed Brown const PetscScalar g_xz = y5 - y1 - y4 + y0; 903552f7358SJed Brown const PetscScalar h_xz = z5 - z1 - z4 + z0; 904552f7358SJed Brown const PetscScalar f_xyz = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 905552f7358SJed Brown const PetscScalar g_xyz = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 906552f7358SJed Brown const PetscScalar h_xyz = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 90756044e6dSMatthew G. Knepley const PetscScalar *ref; 908552f7358SJed Brown PetscErrorCode ierr; 909552f7358SJed Brown 910552f7358SJed Brown PetscFunctionBegin; 91156044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 912552f7358SJed Brown { 913552f7358SJed Brown const PetscScalar x = ref[0]; 914552f7358SJed Brown const PetscScalar y = ref[1]; 915552f7358SJed Brown const PetscScalar z = ref[2]; 916552f7358SJed Brown const PetscInt rows[3] = {0, 1, 2}; 917da80777bSKarl Rupp PetscScalar values[9]; 918da80777bSKarl Rupp 919da80777bSKarl Rupp values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0; 920da80777bSKarl Rupp values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0; 921da80777bSKarl Rupp values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0; 922da80777bSKarl Rupp values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0; 923da80777bSKarl Rupp values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0; 924da80777bSKarl Rupp values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0; 925da80777bSKarl Rupp values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0; 926da80777bSKarl Rupp values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0; 927da80777bSKarl Rupp values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0; 9281aa26658SKarl Rupp 92994ab13aaSBarry Smith ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr); 930552f7358SJed Brown } 931552f7358SJed Brown ierr = PetscLogFlops(152);CHKERRQ(ierr); 93256044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 93394ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 93494ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 935552f7358SJed Brown PetscFunctionReturn(0); 936552f7358SJed Brown } 937552f7358SJed Brown 9389fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 939a6dfd86eSKarl Rupp { 940fafc0619SMatthew G Knepley DM dmCoord; 941552f7358SJed Brown SNES snes; 942552f7358SJed Brown KSP ksp; 943552f7358SJed Brown PC pc; 944552f7358SJed Brown Vec coordsLocal, r, ref, real; 945552f7358SJed Brown Mat J; 94656044e6dSMatthew G. Knepley const PetscScalar *coords; 94756044e6dSMatthew G. Knepley PetscScalar *a; 948552f7358SJed Brown PetscInt p; 949552f7358SJed Brown PetscErrorCode ierr; 950552f7358SJed Brown 951552f7358SJed Brown PetscFunctionBegin; 952552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 953fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 954552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 955552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr); 956552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 957552f7358SJed Brown ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr); 958c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 959552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 960552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 961552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 962552f7358SJed Brown ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr); 963552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 964552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 9650298fd71SBarry Smith ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr); 9660298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr); 967552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 968552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 969552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 970552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 971552f7358SJed Brown 97256044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 973552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 974552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 975a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 976552f7358SJed Brown PetscScalar *xi; 977cb313848SJed Brown PetscReal xir[3]; 978552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 979552f7358SJed Brown 980552f7358SJed Brown /* Can make this do all points at once */ 9810298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 982*cfe5744fSMatthew G. Knepley PetscCheck(8*3 == coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid coordinate closure size %" PetscInt_FMT " should be %d", coordSize, 8*3); 9830298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 984*cfe5744fSMatthew G. Knepley PetscCheck((8*ctx->dof == xSize) || (ctx->dof == xSize),ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input closure size %" PetscInt_FMT " should be %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 8*ctx->dof, ctx->dof); 9853ec1f749SStefano Zampini ierr = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr); 9863ec1f749SStefano Zampini ierr = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr); 987552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 988552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 989552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 990552f7358SJed Brown xi[2] = coords[p*ctx->dim+2]; 991552f7358SJed Brown ierr = VecRestoreArray(real, &xi);CHKERRQ(ierr); 992552f7358SJed Brown ierr = SNESSolve(snes, real, ref);CHKERRQ(ierr); 993552f7358SJed Brown ierr = VecGetArray(ref, &xi);CHKERRQ(ierr); 994cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 995cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 996cb313848SJed Brown xir[2] = PetscRealPart(xi[2]); 997*cfe5744fSMatthew G. Knepley if (8*ctx->dof == xSize) { 998552f7358SJed Brown for (comp = 0; comp < ctx->dof; ++comp) { 999552f7358SJed Brown a[p*ctx->dof+comp] = 1000cb313848SJed Brown x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) + 10017a1931ceSMatthew G. Knepley x[3*ctx->dof+comp]* xir[0]*(1-xir[1])*(1-xir[2]) + 1002cb313848SJed Brown x[2*ctx->dof+comp]* xir[0]* xir[1]*(1-xir[2]) + 10037a1931ceSMatthew G. Knepley x[1*ctx->dof+comp]*(1-xir[0])* xir[1]*(1-xir[2]) + 1004cb313848SJed Brown x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])* xir[2] + 1005cb313848SJed Brown x[5*ctx->dof+comp]* xir[0]*(1-xir[1])* xir[2] + 1006cb313848SJed Brown x[6*ctx->dof+comp]* xir[0]* xir[1]* xir[2] + 1007cb313848SJed Brown x[7*ctx->dof+comp]*(1-xir[0])* xir[1]* xir[2]; 1008552f7358SJed Brown } 1009*cfe5744fSMatthew G. Knepley } else { 1010*cfe5744fSMatthew G. Knepley for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 1011*cfe5744fSMatthew G. Knepley } 1012552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 10130298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 10140298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 1015552f7358SJed Brown } 1016552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 101756044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 1018552f7358SJed Brown 1019552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 1020552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 1021552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 1022552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 1023552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 1024552f7358SJed Brown PetscFunctionReturn(0); 1025552f7358SJed Brown } 1026552f7358SJed Brown 10274267b1a3SMatthew G. Knepley /*@C 10284267b1a3SMatthew G. Knepley DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points. 10294267b1a3SMatthew G. Knepley 1030552f7358SJed Brown Input Parameters: 1031552f7358SJed Brown + ctx - The DMInterpolationInfo context 1032552f7358SJed Brown . dm - The DM 1033552f7358SJed Brown - x - The local vector containing the field to be interpolated 1034552f7358SJed Brown 1035552f7358SJed Brown Output Parameters: 1036552f7358SJed Brown . v - The vector containing the interpolated values 10374267b1a3SMatthew G. Knepley 10384267b1a3SMatthew G. Knepley Note: A suitable v can be obtained using DMInterpolationGetVector(). 10394267b1a3SMatthew G. Knepley 10404267b1a3SMatthew G. Knepley Level: beginner 10414267b1a3SMatthew G. Knepley 10424267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationAddPoints(), DMInterpolationCreate() 10434267b1a3SMatthew G. Knepley @*/ 10440adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v) 10450adebc6cSBarry Smith { 104666a0a883SMatthew G. Knepley PetscDS ds; 104766a0a883SMatthew G. Knepley PetscInt n, p, Nf, field; 104866a0a883SMatthew G. Knepley PetscBool useDS = PETSC_FALSE; 1049552f7358SJed Brown PetscErrorCode ierr; 1050552f7358SJed Brown 1051552f7358SJed Brown PetscFunctionBegin; 1052552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1053552f7358SJed Brown PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 1054552f7358SJed Brown PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 1055552f7358SJed Brown ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr); 10562c71b3e2SJacob Faibussowitsch PetscCheckFalse(n != ctx->n*ctx->dof,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %D should be %D", n, ctx->n*ctx->dof); 105766a0a883SMatthew G. Knepley if (!n) PetscFunctionReturn(0); 1058680d18d5SMatthew G. Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 1059680d18d5SMatthew G. Knepley if (ds) { 106066a0a883SMatthew G. Knepley useDS = PETSC_TRUE; 1061680d18d5SMatthew G. Knepley ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 1062680d18d5SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 106366a0a883SMatthew G. Knepley PetscObject obj; 1064680d18d5SMatthew G. Knepley PetscClassId id; 1065680d18d5SMatthew G. Knepley 106666a0a883SMatthew G. Knepley ierr = PetscDSGetDiscretization(ds, field, &obj);CHKERRQ(ierr); 106766a0a883SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 106866a0a883SMatthew G. Knepley if (id != PETSCFE_CLASSID) {useDS = PETSC_FALSE; break;} 106966a0a883SMatthew G. Knepley } 107066a0a883SMatthew G. Knepley } 107166a0a883SMatthew G. Knepley if (useDS) { 107266a0a883SMatthew G. Knepley const PetscScalar *coords; 107366a0a883SMatthew G. Knepley PetscScalar *interpolant; 107466a0a883SMatthew G. Knepley PetscInt cdim, d; 107566a0a883SMatthew G. Knepley 107666a0a883SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 1077680d18d5SMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 1078680d18d5SMatthew G. Knepley ierr = VecGetArrayWrite(v, &interpolant);CHKERRQ(ierr); 1079680d18d5SMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 108066a0a883SMatthew G. Knepley PetscReal pcoords[3], xi[3]; 1081680d18d5SMatthew G. Knepley PetscScalar *xa = NULL; 108266a0a883SMatthew G. Knepley PetscInt coff = 0, foff = 0, clSize; 1083680d18d5SMatthew G. Knepley 108452aa1562SMatthew G. Knepley if (ctx->cells[p] < 0) continue; 1085680d18d5SMatthew G. Knepley for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p*cdim+d]); 1086680d18d5SMatthew G. Knepley ierr = DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi);CHKERRQ(ierr); 108766a0a883SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr); 108866a0a883SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 108966a0a883SMatthew G. Knepley PetscTabulation T; 109066a0a883SMatthew G. Knepley PetscFE fe; 109166a0a883SMatthew G. Knepley 109266a0a883SMatthew G. Knepley ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr); 1093680d18d5SMatthew G. Knepley ierr = PetscFECreateTabulation(fe, 1, 1, xi, 0, &T);CHKERRQ(ierr); 1094680d18d5SMatthew G. Knepley { 1095680d18d5SMatthew G. Knepley const PetscReal *basis = T->T[0]; 1096680d18d5SMatthew G. Knepley const PetscInt Nb = T->Nb; 1097680d18d5SMatthew G. Knepley const PetscInt Nc = T->Nc; 109866a0a883SMatthew G. Knepley PetscInt f, fc; 109966a0a883SMatthew G. Knepley 1100680d18d5SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 110166a0a883SMatthew G. Knepley interpolant[p*ctx->dof+coff+fc] = 0.0; 1102680d18d5SMatthew G. Knepley for (f = 0; f < Nb; ++f) { 110366a0a883SMatthew G. Knepley interpolant[p*ctx->dof+coff+fc] += xa[foff+f]*basis[(0*Nb + f)*Nc + fc]; 1104552f7358SJed Brown } 1105680d18d5SMatthew G. Knepley } 110666a0a883SMatthew G. Knepley coff += Nc; 110766a0a883SMatthew G. Knepley foff += Nb; 1108680d18d5SMatthew G. Knepley } 1109680d18d5SMatthew G. Knepley ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr); 1110680d18d5SMatthew G. Knepley } 111166a0a883SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr); 11122c71b3e2SJacob Faibussowitsch PetscCheckFalse(coff != ctx->dof,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %D != %D dof specified for interpolation", coff, ctx->dof); 11132c71b3e2SJacob Faibussowitsch PetscCheckFalse(foff != clSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total FE space size %D != %D closure size", foff, clSize); 111466a0a883SMatthew G. Knepley } 1115680d18d5SMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 111666a0a883SMatthew G. Knepley ierr = VecRestoreArrayWrite(v, &interpolant);CHKERRQ(ierr); 111766a0a883SMatthew G. Knepley } else { 111866a0a883SMatthew G. Knepley DMPolytopeType ct; 111966a0a883SMatthew G. Knepley 1120680d18d5SMatthew G. Knepley /* TODO Check each cell individually */ 1121680d18d5SMatthew G. Knepley ierr = DMPlexGetCellType(dm, ctx->cells[0], &ct);CHKERRQ(ierr); 1122680d18d5SMatthew G. Knepley switch (ct) { 1123*cfe5744fSMatthew G. Knepley case DM_POLYTOPE_SEGMENT: ierr = DMInterpolate_Segment_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1124680d18d5SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1125680d18d5SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1126680d18d5SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1127680d18d5SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1128*cfe5744fSMatthew G. Knepley default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for cell type %s", DMPolytopeTypes[PetscMax(0, PetscMin(ct, DM_NUM_POLYTOPES))]); 1129680d18d5SMatthew G. Knepley } 1130552f7358SJed Brown } 1131552f7358SJed Brown PetscFunctionReturn(0); 1132552f7358SJed Brown } 1133552f7358SJed Brown 11344267b1a3SMatthew G. Knepley /*@C 11354267b1a3SMatthew G. Knepley DMInterpolationDestroy - Destroys a DMInterpolationInfo context 11364267b1a3SMatthew G. Knepley 11374267b1a3SMatthew G. Knepley Collective on ctx 11384267b1a3SMatthew G. Knepley 11394267b1a3SMatthew G. Knepley Input Parameter: 11404267b1a3SMatthew G. Knepley . ctx - the context 11414267b1a3SMatthew G. Knepley 11424267b1a3SMatthew G. Knepley Level: beginner 11434267b1a3SMatthew G. Knepley 11444267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 11454267b1a3SMatthew G. Knepley @*/ 11460adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx) 11470adebc6cSBarry Smith { 1148552f7358SJed Brown PetscErrorCode ierr; 1149552f7358SJed Brown 1150552f7358SJed Brown PetscFunctionBegin; 1151064a246eSJacob Faibussowitsch PetscValidPointer(ctx, 1); 1152552f7358SJed Brown ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr); 1153552f7358SJed Brown ierr = PetscFree((*ctx)->points);CHKERRQ(ierr); 1154552f7358SJed Brown ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr); 1155552f7358SJed Brown ierr = PetscFree(*ctx);CHKERRQ(ierr); 11560298fd71SBarry Smith *ctx = NULL; 1157552f7358SJed Brown PetscFunctionReturn(0); 1158552f7358SJed Brown } 1159cc0c4584SMatthew G. Knepley 1160cc0c4584SMatthew G. Knepley /*@C 1161cc0c4584SMatthew G. Knepley SNESMonitorFields - Monitors the residual for each field separately 1162cc0c4584SMatthew G. Knepley 1163cc0c4584SMatthew G. Knepley Collective on SNES 1164cc0c4584SMatthew G. Knepley 1165cc0c4584SMatthew G. Knepley Input Parameters: 1166cc0c4584SMatthew G. Knepley + snes - the SNES context 1167cc0c4584SMatthew G. Knepley . its - iteration number 1168cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual 1169d43b4f6eSBarry Smith - vf - PetscViewerAndFormat of type ASCII 1170cc0c4584SMatthew G. Knepley 1171cc0c4584SMatthew G. Knepley Notes: 1172cc0c4584SMatthew G. Knepley This routine prints the residual norm at each iteration. 1173cc0c4584SMatthew G. Knepley 1174cc0c4584SMatthew G. Knepley Level: intermediate 1175cc0c4584SMatthew G. Knepley 1176cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault() 1177cc0c4584SMatthew G. Knepley @*/ 1178d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 1179cc0c4584SMatthew G. Knepley { 1180d43b4f6eSBarry Smith PetscViewer viewer = vf->viewer; 1181cc0c4584SMatthew G. Knepley Vec res; 1182cc0c4584SMatthew G. Knepley DM dm; 1183cc0c4584SMatthew G. Knepley PetscSection s; 1184cc0c4584SMatthew G. Knepley const PetscScalar *r; 1185cc0c4584SMatthew G. Knepley PetscReal *lnorms, *norms; 1186cc0c4584SMatthew G. Knepley PetscInt numFields, f, pStart, pEnd, p; 1187cc0c4584SMatthew G. Knepley PetscErrorCode ierr; 1188cc0c4584SMatthew G. Knepley 1189cc0c4584SMatthew G. Knepley PetscFunctionBegin; 11904d4332d5SBarry Smith PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 11919e5d0892SLisandro Dalcin ierr = SNESGetFunction(snes, &res, NULL, NULL);CHKERRQ(ierr); 1192cc0c4584SMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 119392fd8e1eSJed Brown ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 1194cc0c4584SMatthew G. Knepley ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr); 1195cc0c4584SMatthew G. Knepley ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1196cc0c4584SMatthew G. Knepley ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr); 1197cc0c4584SMatthew G. Knepley ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr); 1198cc0c4584SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1199cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 1200cc0c4584SMatthew G. Knepley PetscInt fdof, foff, d; 1201cc0c4584SMatthew G. Knepley 1202cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr); 1203cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr); 1204cc0c4584SMatthew G. Knepley for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d])); 1205cc0c4584SMatthew G. Knepley } 1206cc0c4584SMatthew G. Knepley } 1207cc0c4584SMatthew G. Knepley ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr); 1208820f2d46SBarry Smith ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 1209d43b4f6eSBarry Smith ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1210cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 1211cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr); 1212cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 1213cc0c4584SMatthew G. Knepley if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1214cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr); 1215cc0c4584SMatthew G. Knepley } 1216cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr); 1217cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 1218d43b4f6eSBarry Smith ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1219cc0c4584SMatthew G. Knepley ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr); 1220cc0c4584SMatthew G. Knepley PetscFunctionReturn(0); 1221cc0c4584SMatthew G. Knepley } 122224cdb843SMatthew G. Knepley 122324cdb843SMatthew G. Knepley /********************* Residual Computation **************************/ 122424cdb843SMatthew G. Knepley 12256528b96dSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 12266528b96dSMatthew G. Knepley { 12276528b96dSMatthew G. Knepley PetscInt depth; 12286528b96dSMatthew G. Knepley PetscErrorCode ierr; 12296528b96dSMatthew G. Knepley 12306528b96dSMatthew G. Knepley PetscFunctionBegin; 12316528b96dSMatthew G. Knepley ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 12326528b96dSMatthew G. Knepley ierr = DMGetStratumIS(plex, "dim", depth, cellIS);CHKERRQ(ierr); 12336528b96dSMatthew G. Knepley if (!*cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, cellIS);CHKERRQ(ierr);} 12346528b96dSMatthew G. Knepley PetscFunctionReturn(0); 12356528b96dSMatthew G. Knepley } 12366528b96dSMatthew G. Knepley 123724cdb843SMatthew G. Knepley /*@ 12388db23a53SJed Brown DMPlexSNESComputeResidualFEM - Sums the local residual into vector F from the local input X using pointwise functions specified by the user 123924cdb843SMatthew G. Knepley 124024cdb843SMatthew G. Knepley Input Parameters: 124124cdb843SMatthew G. Knepley + dm - The mesh 124224cdb843SMatthew G. Knepley . X - Local solution 124324cdb843SMatthew G. Knepley - user - The user context 124424cdb843SMatthew G. Knepley 124524cdb843SMatthew G. Knepley Output Parameter: 124624cdb843SMatthew G. Knepley . F - Local output vector 124724cdb843SMatthew G. Knepley 12488db23a53SJed Brown Notes: 12498db23a53SJed Brown The residual is summed into F; the caller is responsible for using VecZeroEntries() or otherwise ensuring that any data in F is intentional. 12508db23a53SJed Brown 125124cdb843SMatthew G. Knepley Level: developer 125224cdb843SMatthew G. Knepley 12537a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 125424cdb843SMatthew G. Knepley @*/ 125524cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 125624cdb843SMatthew G. Knepley { 12576da023fcSToby Isaac DM plex; 1258083401c6SMatthew G. Knepley IS allcellIS; 12596528b96dSMatthew G. Knepley PetscInt Nds, s; 126024cdb843SMatthew G. Knepley PetscErrorCode ierr; 126124cdb843SMatthew G. Knepley 126224cdb843SMatthew G. Knepley PetscFunctionBegin; 12636da023fcSToby Isaac ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 12646528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 12656528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 12666528b96dSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 12676528b96dSMatthew G. Knepley PetscDS ds; 12686528b96dSMatthew G. Knepley IS cellIS; 126906ad1575SMatthew G. Knepley PetscFormKey key; 12706528b96dSMatthew G. Knepley 12716528b96dSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr); 12726528b96dSMatthew G. Knepley key.value = 0; 12736528b96dSMatthew G. Knepley key.field = 0; 127406ad1575SMatthew G. Knepley key.part = 0; 12756528b96dSMatthew G. Knepley if (!key.label) { 12766528b96dSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 12776528b96dSMatthew G. Knepley cellIS = allcellIS; 12786528b96dSMatthew G. Knepley } else { 12796528b96dSMatthew G. Knepley IS pointIS; 12806528b96dSMatthew G. Knepley 12816528b96dSMatthew G. Knepley key.value = 1; 12826528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr); 12836528b96dSMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 12846528b96dSMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 12856528b96dSMatthew G. Knepley } 12866528b96dSMatthew G. Knepley ierr = DMPlexComputeResidual_Internal(plex, key, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr); 12876528b96dSMatthew G. Knepley ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 12886528b96dSMatthew G. Knepley } 12896528b96dSMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 12906528b96dSMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 12916528b96dSMatthew G. Knepley PetscFunctionReturn(0); 12926528b96dSMatthew G. Knepley } 12936528b96dSMatthew G. Knepley 12946528b96dSMatthew G. Knepley PetscErrorCode DMSNESComputeResidual(DM dm, Vec X, Vec F, void *user) 12956528b96dSMatthew G. Knepley { 12966528b96dSMatthew G. Knepley DM plex; 12976528b96dSMatthew G. Knepley IS allcellIS; 12986528b96dSMatthew G. Knepley PetscInt Nds, s; 12996528b96dSMatthew G. Knepley PetscErrorCode ierr; 13006528b96dSMatthew G. Knepley 13016528b96dSMatthew G. Knepley PetscFunctionBegin; 13026528b96dSMatthew G. Knepley ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 13036528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 13046528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1305083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1306083401c6SMatthew G. Knepley PetscDS ds; 1307083401c6SMatthew G. Knepley DMLabel label; 1308083401c6SMatthew G. Knepley IS cellIS; 1309083401c6SMatthew G. Knepley 1310083401c6SMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr); 13116528b96dSMatthew G. Knepley { 131206ad1575SMatthew G. Knepley PetscWeakFormKind resmap[2] = {PETSC_WF_F0, PETSC_WF_F1}; 13136528b96dSMatthew G. Knepley PetscWeakForm wf; 13146528b96dSMatthew G. Knepley PetscInt Nm = 2, m, Nk = 0, k, kp, off = 0; 131506ad1575SMatthew G. Knepley PetscFormKey *reskeys; 13166528b96dSMatthew G. Knepley 13176528b96dSMatthew G. Knepley /* Get unique residual keys */ 13186528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 13196528b96dSMatthew G. Knepley PetscInt Nkm; 132006ad1575SMatthew G. Knepley ierr = PetscHMapFormGetSize(ds->wf->form[resmap[m]], &Nkm);CHKERRQ(ierr); 13216528b96dSMatthew G. Knepley Nk += Nkm; 13226528b96dSMatthew G. Knepley } 13236528b96dSMatthew G. Knepley ierr = PetscMalloc1(Nk, &reskeys);CHKERRQ(ierr); 13246528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 132506ad1575SMatthew G. Knepley ierr = PetscHMapFormGetKeys(ds->wf->form[resmap[m]], &off, reskeys);CHKERRQ(ierr); 13266528b96dSMatthew G. Knepley } 13272c71b3e2SJacob Faibussowitsch PetscCheckFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk); 132806ad1575SMatthew G. Knepley ierr = PetscFormKeySort(Nk, reskeys);CHKERRQ(ierr); 13296528b96dSMatthew G. Knepley for (k = 0, kp = 1; kp < Nk; ++kp) { 13306528b96dSMatthew G. Knepley if ((reskeys[k].label != reskeys[kp].label) || (reskeys[k].value != reskeys[kp].value)) { 13316528b96dSMatthew G. Knepley ++k; 13326528b96dSMatthew G. Knepley if (kp != k) reskeys[k] = reskeys[kp]; 13336528b96dSMatthew G. Knepley } 13346528b96dSMatthew G. Knepley } 13356528b96dSMatthew G. Knepley Nk = k; 13366528b96dSMatthew G. Knepley 13376528b96dSMatthew G. Knepley ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 13386528b96dSMatthew G. Knepley for (k = 0; k < Nk; ++k) { 13396528b96dSMatthew G. Knepley DMLabel label = reskeys[k].label; 13406528b96dSMatthew G. Knepley PetscInt val = reskeys[k].value; 13416528b96dSMatthew G. Knepley 1342083401c6SMatthew G. Knepley if (!label) { 1343083401c6SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 1344083401c6SMatthew G. Knepley cellIS = allcellIS; 1345083401c6SMatthew G. Knepley } else { 1346083401c6SMatthew G. Knepley IS pointIS; 1347083401c6SMatthew G. Knepley 13486528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr); 1349083401c6SMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 1350083401c6SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 13514a3e9fdbSToby Isaac } 13526528b96dSMatthew G. Knepley ierr = DMPlexComputeResidual_Internal(plex, reskeys[k], cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr); 13534a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 1354083401c6SMatthew G. Knepley } 13556528b96dSMatthew G. Knepley ierr = PetscFree(reskeys);CHKERRQ(ierr); 13566528b96dSMatthew G. Knepley } 13576528b96dSMatthew G. Knepley } 1358083401c6SMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 13599a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 136024cdb843SMatthew G. Knepley PetscFunctionReturn(0); 136124cdb843SMatthew G. Knepley } 136224cdb843SMatthew G. Knepley 1363bdd6f66aSToby Isaac /*@ 1364bdd6f66aSToby Isaac DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X 1365bdd6f66aSToby Isaac 1366bdd6f66aSToby Isaac Input Parameters: 1367bdd6f66aSToby Isaac + dm - The mesh 1368bdd6f66aSToby Isaac - user - The user context 1369bdd6f66aSToby Isaac 1370bdd6f66aSToby Isaac Output Parameter: 1371bdd6f66aSToby Isaac . X - Local solution 1372bdd6f66aSToby Isaac 1373bdd6f66aSToby Isaac Level: developer 1374bdd6f66aSToby Isaac 13757a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 1376bdd6f66aSToby Isaac @*/ 1377bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user) 1378bdd6f66aSToby Isaac { 1379bdd6f66aSToby Isaac DM plex; 1380bdd6f66aSToby Isaac PetscErrorCode ierr; 1381bdd6f66aSToby Isaac 1382bdd6f66aSToby Isaac PetscFunctionBegin; 1383bdd6f66aSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 1384bdd6f66aSToby Isaac ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr); 1385bdd6f66aSToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 1386bdd6f66aSToby Isaac PetscFunctionReturn(0); 1387bdd6f66aSToby Isaac } 1388bdd6f66aSToby Isaac 13897a73cf09SMatthew G. Knepley /*@ 13908e3a2eefSMatthew G. Knepley DMSNESComputeJacobianAction - Compute the action of the Jacobian J(X) on Y 13917a73cf09SMatthew G. Knepley 13927a73cf09SMatthew G. Knepley Input Parameters: 13938e3a2eefSMatthew G. Knepley + dm - The DM 13947a73cf09SMatthew G. Knepley . X - Local solution vector 13957a73cf09SMatthew G. Knepley . Y - Local input vector 13967a73cf09SMatthew G. Knepley - user - The user context 13977a73cf09SMatthew G. Knepley 13987a73cf09SMatthew G. Knepley Output Parameter: 13998e3a2eefSMatthew G. Knepley . F - lcoal output vector 14007a73cf09SMatthew G. Knepley 14017a73cf09SMatthew G. Knepley Level: developer 14027a73cf09SMatthew G. Knepley 14038e3a2eefSMatthew G. Knepley Notes: 14048e3a2eefSMatthew G. Knepley Users will typically use DMSNESCreateJacobianMF() followed by MatMult() instead of calling this routine directly. 14058e3a2eefSMatthew G. Knepley 1406a509fe9cSSatish Balay .seealso: DMSNESCreateJacobianMF(), DMPlexSNESComputeResidualFEM() 14077a73cf09SMatthew G. Knepley @*/ 14088e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESComputeJacobianAction(DM dm, Vec X, Vec Y, Vec F, void *user) 1409a925c78cSMatthew G. Knepley { 14108e3a2eefSMatthew G. Knepley DM plex; 14118e3a2eefSMatthew G. Knepley IS allcellIS; 14128e3a2eefSMatthew G. Knepley PetscInt Nds, s; 1413a925c78cSMatthew G. Knepley PetscErrorCode ierr; 1414a925c78cSMatthew G. Knepley 1415a925c78cSMatthew G. Knepley PetscFunctionBegin; 14167a73cf09SMatthew G. Knepley ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 14178e3a2eefSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 14188e3a2eefSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 14198e3a2eefSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 14208e3a2eefSMatthew G. Knepley PetscDS ds; 14218e3a2eefSMatthew G. Knepley DMLabel label; 14228e3a2eefSMatthew G. Knepley IS cellIS; 14237a73cf09SMatthew G. Knepley 14248e3a2eefSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr); 14258e3a2eefSMatthew G. Knepley { 142606ad1575SMatthew G. Knepley PetscWeakFormKind jacmap[4] = {PETSC_WF_G0, PETSC_WF_G1, PETSC_WF_G2, PETSC_WF_G3}; 14278e3a2eefSMatthew G. Knepley PetscWeakForm wf; 14288e3a2eefSMatthew G. Knepley PetscInt Nm = 4, m, Nk = 0, k, kp, off = 0; 142906ad1575SMatthew G. Knepley PetscFormKey *jackeys; 14308e3a2eefSMatthew G. Knepley 14318e3a2eefSMatthew G. Knepley /* Get unique Jacobian keys */ 14328e3a2eefSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 14338e3a2eefSMatthew G. Knepley PetscInt Nkm; 143406ad1575SMatthew G. Knepley ierr = PetscHMapFormGetSize(ds->wf->form[jacmap[m]], &Nkm);CHKERRQ(ierr); 14358e3a2eefSMatthew G. Knepley Nk += Nkm; 14368e3a2eefSMatthew G. Knepley } 14378e3a2eefSMatthew G. Knepley ierr = PetscMalloc1(Nk, &jackeys);CHKERRQ(ierr); 14388e3a2eefSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 143906ad1575SMatthew G. Knepley ierr = PetscHMapFormGetKeys(ds->wf->form[jacmap[m]], &off, jackeys);CHKERRQ(ierr); 14408e3a2eefSMatthew G. Knepley } 14412c71b3e2SJacob Faibussowitsch PetscCheckFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk); 144206ad1575SMatthew G. Knepley ierr = PetscFormKeySort(Nk, jackeys);CHKERRQ(ierr); 14438e3a2eefSMatthew G. Knepley for (k = 0, kp = 1; kp < Nk; ++kp) { 14448e3a2eefSMatthew G. Knepley if ((jackeys[k].label != jackeys[kp].label) || (jackeys[k].value != jackeys[kp].value)) { 14458e3a2eefSMatthew G. Knepley ++k; 14468e3a2eefSMatthew G. Knepley if (kp != k) jackeys[k] = jackeys[kp]; 14478e3a2eefSMatthew G. Knepley } 14488e3a2eefSMatthew G. Knepley } 14498e3a2eefSMatthew G. Knepley Nk = k; 14508e3a2eefSMatthew G. Knepley 14518e3a2eefSMatthew G. Knepley ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 14528e3a2eefSMatthew G. Knepley for (k = 0; k < Nk; ++k) { 14538e3a2eefSMatthew G. Knepley DMLabel label = jackeys[k].label; 14548e3a2eefSMatthew G. Knepley PetscInt val = jackeys[k].value; 14558e3a2eefSMatthew G. Knepley 14568e3a2eefSMatthew G. Knepley if (!label) { 14578e3a2eefSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 14588e3a2eefSMatthew G. Knepley cellIS = allcellIS; 14597a73cf09SMatthew G. Knepley } else { 14608e3a2eefSMatthew G. Knepley IS pointIS; 1461a925c78cSMatthew G. Knepley 14628e3a2eefSMatthew G. Knepley ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr); 14638e3a2eefSMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 14648e3a2eefSMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1465a925c78cSMatthew G. Knepley } 14668e3a2eefSMatthew G. Knepley ierr = DMPlexComputeJacobian_Action_Internal(plex, jackeys[k], cellIS, 0.0, 0.0, X, NULL, Y, F, user);CHKERRQ(ierr); 14677a73cf09SMatthew G. Knepley ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 14688e3a2eefSMatthew G. Knepley } 14698e3a2eefSMatthew G. Knepley ierr = PetscFree(jackeys);CHKERRQ(ierr); 14708e3a2eefSMatthew G. Knepley } 14718e3a2eefSMatthew G. Knepley } 14728e3a2eefSMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 14737a73cf09SMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 1474a925c78cSMatthew G. Knepley PetscFunctionReturn(0); 1475a925c78cSMatthew G. Knepley } 1476a925c78cSMatthew G. Knepley 147724cdb843SMatthew G. Knepley /*@ 147824cdb843SMatthew G. Knepley DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 147924cdb843SMatthew G. Knepley 148024cdb843SMatthew G. Knepley Input Parameters: 148124cdb843SMatthew G. Knepley + dm - The mesh 148224cdb843SMatthew G. Knepley . X - Local input vector 148324cdb843SMatthew G. Knepley - user - The user context 148424cdb843SMatthew G. Knepley 148524cdb843SMatthew G. Knepley Output Parameter: 148624cdb843SMatthew G. Knepley . Jac - Jacobian matrix 148724cdb843SMatthew G. Knepley 148824cdb843SMatthew G. Knepley Note: 148924cdb843SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 149024cdb843SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 149124cdb843SMatthew G. Knepley 149224cdb843SMatthew G. Knepley Level: developer 149324cdb843SMatthew G. Knepley 149424cdb843SMatthew G. Knepley .seealso: FormFunctionLocal() 149524cdb843SMatthew G. Knepley @*/ 149624cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user) 149724cdb843SMatthew G. Knepley { 14986da023fcSToby Isaac DM plex; 1499083401c6SMatthew G. Knepley IS allcellIS; 1500f04eb4edSMatthew G. Knepley PetscBool hasJac, hasPrec; 15016528b96dSMatthew G. Knepley PetscInt Nds, s; 150224cdb843SMatthew G. Knepley PetscErrorCode ierr; 150324cdb843SMatthew G. Knepley 150424cdb843SMatthew G. Knepley PetscFunctionBegin; 15056da023fcSToby Isaac ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 15066528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 15076528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1508083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1509083401c6SMatthew G. Knepley PetscDS ds; 1510083401c6SMatthew G. Knepley IS cellIS; 151106ad1575SMatthew G. Knepley PetscFormKey key; 1512083401c6SMatthew G. Knepley 15136528b96dSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr); 15146528b96dSMatthew G. Knepley key.value = 0; 15156528b96dSMatthew G. Knepley key.field = 0; 151606ad1575SMatthew G. Knepley key.part = 0; 15176528b96dSMatthew G. Knepley if (!key.label) { 1518083401c6SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 1519083401c6SMatthew G. Knepley cellIS = allcellIS; 1520083401c6SMatthew G. Knepley } else { 1521083401c6SMatthew G. Knepley IS pointIS; 1522083401c6SMatthew G. Knepley 15236528b96dSMatthew G. Knepley key.value = 1; 15246528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr); 1525083401c6SMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 1526083401c6SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1527083401c6SMatthew G. Knepley } 1528083401c6SMatthew G. Knepley if (!s) { 1529083401c6SMatthew G. Knepley ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr); 1530083401c6SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr); 1531f04eb4edSMatthew G. Knepley if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);} 1532f04eb4edSMatthew G. Knepley ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 1533083401c6SMatthew G. Knepley } 15346528b96dSMatthew G. Knepley ierr = DMPlexComputeJacobian_Internal(plex, key, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr); 15354a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 1536083401c6SMatthew G. Knepley } 1537083401c6SMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 15389a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 153924cdb843SMatthew G. Knepley PetscFunctionReturn(0); 154024cdb843SMatthew G. Knepley } 15411878804aSMatthew G. Knepley 15428e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx 15438e3a2eefSMatthew G. Knepley { 15448e3a2eefSMatthew G. Knepley DM dm; 15458e3a2eefSMatthew G. Knepley Vec X; 15468e3a2eefSMatthew G. Knepley void *ctx; 15478e3a2eefSMatthew G. Knepley }; 15488e3a2eefSMatthew G. Knepley 15498e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Destroy_Private(Mat A) 15508e3a2eefSMatthew G. Knepley { 15518e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15528e3a2eefSMatthew G. Knepley PetscErrorCode ierr; 15538e3a2eefSMatthew G. Knepley 15548e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15553ec1f749SStefano Zampini ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr); 15568e3a2eefSMatthew G. Knepley ierr = MatShellSetContext(A, NULL);CHKERRQ(ierr); 15578e3a2eefSMatthew G. Knepley ierr = DMDestroy(&ctx->dm);CHKERRQ(ierr); 15588e3a2eefSMatthew G. Knepley ierr = VecDestroy(&ctx->X);CHKERRQ(ierr); 15598e3a2eefSMatthew G. Knepley ierr = PetscFree(ctx);CHKERRQ(ierr); 15608e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15618e3a2eefSMatthew G. Knepley } 15628e3a2eefSMatthew G. Knepley 15638e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Mult_Private(Mat A, Vec Y, Vec Z) 15648e3a2eefSMatthew G. Knepley { 15658e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15668e3a2eefSMatthew G. Knepley PetscErrorCode ierr; 15678e3a2eefSMatthew G. Knepley 15688e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15693ec1f749SStefano Zampini ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr); 15708e3a2eefSMatthew G. Knepley ierr = DMSNESComputeJacobianAction(ctx->dm, ctx->X, Y, Z, ctx->ctx);CHKERRQ(ierr); 15718e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15728e3a2eefSMatthew G. Knepley } 15738e3a2eefSMatthew G. Knepley 15748e3a2eefSMatthew G. Knepley /*@ 15758e3a2eefSMatthew G. Knepley DMSNESCreateJacobianMF - Create a Mat which computes the action of the Jacobian matrix-free 15768e3a2eefSMatthew G. Knepley 15778e3a2eefSMatthew G. Knepley Collective on dm 15788e3a2eefSMatthew G. Knepley 15798e3a2eefSMatthew G. Knepley Input Parameters: 15808e3a2eefSMatthew G. Knepley + dm - The DM 15818e3a2eefSMatthew G. Knepley . X - The evaluation point for the Jacobian 15828e3a2eefSMatthew G. Knepley - user - A user context, or NULL 15838e3a2eefSMatthew G. Knepley 15848e3a2eefSMatthew G. Knepley Output Parameter: 15858e3a2eefSMatthew G. Knepley . J - The Mat 15868e3a2eefSMatthew G. Knepley 15878e3a2eefSMatthew G. Knepley Level: advanced 15888e3a2eefSMatthew G. Knepley 15898e3a2eefSMatthew G. Knepley Notes: 15908e3a2eefSMatthew G. Knepley Vec X is kept in Mat J, so updating X then updates the evaluation point. 15918e3a2eefSMatthew G. Knepley 15928e3a2eefSMatthew G. Knepley .seealso: DMSNESComputeJacobianAction() 15938e3a2eefSMatthew G. Knepley @*/ 15948e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESCreateJacobianMF(DM dm, Vec X, void *user, Mat *J) 15958e3a2eefSMatthew G. Knepley { 15968e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15978e3a2eefSMatthew G. Knepley PetscInt n, N; 15988e3a2eefSMatthew G. Knepley PetscErrorCode ierr; 15998e3a2eefSMatthew G. Knepley 16008e3a2eefSMatthew G. Knepley PetscFunctionBegin; 16018e3a2eefSMatthew G. Knepley ierr = MatCreate(PetscObjectComm((PetscObject) dm), J);CHKERRQ(ierr); 16028e3a2eefSMatthew G. Knepley ierr = MatSetType(*J, MATSHELL);CHKERRQ(ierr); 16038e3a2eefSMatthew G. Knepley ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr); 16048e3a2eefSMatthew G. Knepley ierr = VecGetSize(X, &N);CHKERRQ(ierr); 16058e3a2eefSMatthew G. Knepley ierr = MatSetSizes(*J, n, n, N, N);CHKERRQ(ierr); 16068e3a2eefSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 16078e3a2eefSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) X);CHKERRQ(ierr); 16088e3a2eefSMatthew G. Knepley ierr = PetscMalloc1(1, &ctx);CHKERRQ(ierr); 16098e3a2eefSMatthew G. Knepley ctx->dm = dm; 16108e3a2eefSMatthew G. Knepley ctx->X = X; 16118e3a2eefSMatthew G. Knepley ctx->ctx = user; 16128e3a2eefSMatthew G. Knepley ierr = MatShellSetContext(*J, ctx);CHKERRQ(ierr); 16138e3a2eefSMatthew G. Knepley ierr = MatShellSetOperation(*J, MATOP_DESTROY, (void (*)(void)) DMSNESJacobianMF_Destroy_Private);CHKERRQ(ierr); 16148e3a2eefSMatthew G. Knepley ierr = MatShellSetOperation(*J, MATOP_MULT, (void (*)(void)) DMSNESJacobianMF_Mult_Private);CHKERRQ(ierr); 16158e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 16168e3a2eefSMatthew G. Knepley } 16178e3a2eefSMatthew G. Knepley 161838cfc46eSPierre Jolivet /* 161938cfc46eSPierre Jolivet MatComputeNeumannOverlap - Computes an unassembled (Neumann) local overlapping Mat in nonlinear context. 162038cfc46eSPierre Jolivet 162138cfc46eSPierre Jolivet Input Parameters: 162238cfc46eSPierre Jolivet + X - SNES linearization point 162338cfc46eSPierre Jolivet . ovl - index set of overlapping subdomains 162438cfc46eSPierre Jolivet 162538cfc46eSPierre Jolivet Output Parameter: 162638cfc46eSPierre Jolivet . J - unassembled (Neumann) local matrix 162738cfc46eSPierre Jolivet 162838cfc46eSPierre Jolivet Level: intermediate 162938cfc46eSPierre Jolivet 163038cfc46eSPierre Jolivet .seealso: DMCreateNeumannOverlap(), MATIS, PCHPDDMSetAuxiliaryMat() 163138cfc46eSPierre Jolivet */ 163238cfc46eSPierre Jolivet static PetscErrorCode MatComputeNeumannOverlap_Plex(Mat J, PetscReal t, Vec X, Vec X_t, PetscReal s, IS ovl, void *ctx) 163338cfc46eSPierre Jolivet { 163438cfc46eSPierre Jolivet SNES snes; 163538cfc46eSPierre Jolivet Mat pJ; 163638cfc46eSPierre Jolivet DM ovldm,origdm; 163738cfc46eSPierre Jolivet DMSNES sdm; 163838cfc46eSPierre Jolivet PetscErrorCode (*bfun)(DM,Vec,void*); 163938cfc46eSPierre Jolivet PetscErrorCode (*jfun)(DM,Vec,Mat,Mat,void*); 164038cfc46eSPierre Jolivet void *bctx,*jctx; 164138cfc46eSPierre Jolivet PetscErrorCode ierr; 164238cfc46eSPierre Jolivet 164338cfc46eSPierre Jolivet PetscFunctionBegin; 164438cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_MATIS",(PetscObject*)&pJ);CHKERRQ(ierr); 16452c71b3e2SJacob Faibussowitsch PetscCheckFalse(!pJ,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing overlapping Mat"); 164638cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Original_HPDDM",(PetscObject*)&origdm);CHKERRQ(ierr); 16472c71b3e2SJacob Faibussowitsch PetscCheckFalse(!origdm,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing original DM"); 164838cfc46eSPierre Jolivet ierr = MatGetDM(pJ,&ovldm);CHKERRQ(ierr); 164938cfc46eSPierre Jolivet ierr = DMSNESGetBoundaryLocal(origdm,&bfun,&bctx);CHKERRQ(ierr); 165038cfc46eSPierre Jolivet ierr = DMSNESSetBoundaryLocal(ovldm,bfun,bctx);CHKERRQ(ierr); 165138cfc46eSPierre Jolivet ierr = DMSNESGetJacobianLocal(origdm,&jfun,&jctx);CHKERRQ(ierr); 165238cfc46eSPierre Jolivet ierr = DMSNESSetJacobianLocal(ovldm,jfun,jctx);CHKERRQ(ierr); 165338cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject*)&snes);CHKERRQ(ierr); 165438cfc46eSPierre Jolivet if (!snes) { 165538cfc46eSPierre Jolivet ierr = SNESCreate(PetscObjectComm((PetscObject)ovl),&snes);CHKERRQ(ierr); 165638cfc46eSPierre Jolivet ierr = SNESSetDM(snes,ovldm);CHKERRQ(ierr); 165738cfc46eSPierre Jolivet ierr = PetscObjectCompose((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject)snes);CHKERRQ(ierr); 165838cfc46eSPierre Jolivet ierr = PetscObjectDereference((PetscObject)snes);CHKERRQ(ierr); 165938cfc46eSPierre Jolivet } 166038cfc46eSPierre Jolivet ierr = DMGetDMSNES(ovldm,&sdm);CHKERRQ(ierr); 166138cfc46eSPierre Jolivet ierr = VecLockReadPush(X);CHKERRQ(ierr); 166238cfc46eSPierre Jolivet PetscStackPush("SNES user Jacobian function"); 166338cfc46eSPierre Jolivet ierr = (*sdm->ops->computejacobian)(snes,X,pJ,pJ,sdm->jacobianctx);CHKERRQ(ierr); 166438cfc46eSPierre Jolivet PetscStackPop; 166538cfc46eSPierre Jolivet ierr = VecLockReadPop(X);CHKERRQ(ierr); 166638cfc46eSPierre Jolivet /* this is a no-hop, just in case we decide to change the placeholder for the local Neumann matrix */ 166738cfc46eSPierre Jolivet { 166838cfc46eSPierre Jolivet Mat locpJ; 166938cfc46eSPierre Jolivet 167038cfc46eSPierre Jolivet ierr = MatISGetLocalMat(pJ,&locpJ);CHKERRQ(ierr); 167138cfc46eSPierre Jolivet ierr = MatCopy(locpJ,J,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 167238cfc46eSPierre Jolivet } 167338cfc46eSPierre Jolivet PetscFunctionReturn(0); 167438cfc46eSPierre Jolivet } 167538cfc46eSPierre Jolivet 1676a925c78cSMatthew G. Knepley /*@ 16779f520fc2SToby Isaac DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian. 16789f520fc2SToby Isaac 16799f520fc2SToby Isaac Input Parameters: 16809f520fc2SToby Isaac + dm - The DM object 1681dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary()) 16829f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual()) 16839f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian()) 16841a244344SSatish Balay 16851a244344SSatish Balay Level: developer 16869f520fc2SToby Isaac @*/ 16879f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx) 16889f520fc2SToby Isaac { 16899f520fc2SToby Isaac PetscErrorCode ierr; 16909f520fc2SToby Isaac 16919f520fc2SToby Isaac PetscFunctionBegin; 16929f520fc2SToby Isaac ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr); 16939f520fc2SToby Isaac ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr); 16949f520fc2SToby Isaac ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr); 169538cfc46eSPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",MatComputeNeumannOverlap_Plex);CHKERRQ(ierr); 16969f520fc2SToby Isaac PetscFunctionReturn(0); 16979f520fc2SToby Isaac } 16989f520fc2SToby Isaac 1699f017bcb6SMatthew G. Knepley /*@C 1700f017bcb6SMatthew G. Knepley DMSNESCheckDiscretization - Check the discretization error of the exact solution 1701f017bcb6SMatthew G. Knepley 1702f017bcb6SMatthew G. Knepley Input Parameters: 1703f017bcb6SMatthew G. Knepley + snes - the SNES object 1704f017bcb6SMatthew G. Knepley . dm - the DM 1705f2cacb80SMatthew G. Knepley . t - the time 1706f017bcb6SMatthew G. Knepley . u - a DM vector 1707f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1708f017bcb6SMatthew G. Knepley 1709f3c94560SMatthew G. Knepley Output Parameters: 1710f3c94560SMatthew G. Knepley . error - An array which holds the discretization error in each field, or NULL 1711f3c94560SMatthew G. Knepley 17127f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 17137f96f943SMatthew G. Knepley 1714f017bcb6SMatthew G. Knepley Level: developer 1715f017bcb6SMatthew G. Knepley 17167f96f943SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckResidual(), DMSNESCheckJacobian(), PetscDSSetExactSolution() 1717f017bcb6SMatthew G. Knepley @*/ 1718f2cacb80SMatthew G. Knepley PetscErrorCode DMSNESCheckDiscretization(SNES snes, DM dm, PetscReal t, Vec u, PetscReal tol, PetscReal error[]) 17191878804aSMatthew G. Knepley { 1720f017bcb6SMatthew G. Knepley PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 1721f017bcb6SMatthew G. Knepley void **ectxs; 1722f3c94560SMatthew G. Knepley PetscReal *err; 17237f96f943SMatthew G. Knepley MPI_Comm comm; 17247f96f943SMatthew G. Knepley PetscInt Nf, f; 17251878804aSMatthew G. Knepley PetscErrorCode ierr; 17261878804aSMatthew G. Knepley 17271878804aSMatthew G. Knepley PetscFunctionBegin; 1728f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1729f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1730064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(u, VEC_CLASSID, 4); 1731534a8f05SLisandro Dalcin if (error) PetscValidRealPointer(error, 6); 17327f96f943SMatthew G. Knepley 1733f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, t, u, NULL);CHKERRQ(ierr); 17347f96f943SMatthew G. Knepley ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr); 17357f96f943SMatthew G. Knepley 1736f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1737f017bcb6SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 1738083401c6SMatthew G. Knepley ierr = PetscCalloc3(Nf, &exacts, Nf, &ectxs, PetscMax(1, Nf), &err);CHKERRQ(ierr); 17397f96f943SMatthew G. Knepley { 17407f96f943SMatthew G. Knepley PetscInt Nds, s; 17417f96f943SMatthew G. Knepley 1742083401c6SMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1743083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 17447f96f943SMatthew G. Knepley PetscDS ds; 1745083401c6SMatthew G. Knepley DMLabel label; 1746083401c6SMatthew G. Knepley IS fieldIS; 17477f96f943SMatthew G. Knepley const PetscInt *fields; 17487f96f943SMatthew G. Knepley PetscInt dsNf, f; 1749083401c6SMatthew G. Knepley 1750083401c6SMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 1751083401c6SMatthew G. Knepley ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 1752083401c6SMatthew G. Knepley ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 1753083401c6SMatthew G. Knepley for (f = 0; f < dsNf; ++f) { 1754083401c6SMatthew G. Knepley const PetscInt field = fields[f]; 1755083401c6SMatthew G. Knepley ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 1756083401c6SMatthew G. Knepley } 1757083401c6SMatthew G. Knepley ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 1758083401c6SMatthew G. Knepley } 1759083401c6SMatthew G. Knepley } 1760f017bcb6SMatthew G. Knepley if (Nf > 1) { 1761f2cacb80SMatthew G. Knepley ierr = DMComputeL2FieldDiff(dm, t, exacts, ectxs, u, err);CHKERRQ(ierr); 1762f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 1763f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 17642c71b3e2SJacob Faibussowitsch PetscCheckFalse(err[f] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g for field %D exceeds tolerance %g", (double) err[f], f, (double) tol); 17651878804aSMatthew G. Knepley } 1766b878532fSMatthew G. Knepley } else if (error) { 1767b878532fSMatthew G. Knepley for (f = 0; f < Nf; ++f) error[f] = err[f]; 17681878804aSMatthew G. Knepley } else { 1769f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr); 1770f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1771f017bcb6SMatthew G. Knepley if (f) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);} 1772f3c94560SMatthew G. Knepley ierr = PetscPrintf(comm, "%g", (double)err[f]);CHKERRQ(ierr); 17731878804aSMatthew G. Knepley } 1774f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr); 1775f017bcb6SMatthew G. Knepley } 1776f017bcb6SMatthew G. Knepley } else { 1777f2cacb80SMatthew G. Knepley ierr = DMComputeL2Diff(dm, t, exacts, ectxs, u, &err[0]);CHKERRQ(ierr); 1778f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 17792c71b3e2SJacob Faibussowitsch PetscCheckFalse(err[0] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g exceeds tolerance %g", (double) err[0], (double) tol); 1780b878532fSMatthew G. Knepley } else if (error) { 1781b878532fSMatthew G. Knepley error[0] = err[0]; 1782f017bcb6SMatthew G. Knepley } else { 1783f3c94560SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Error: %g\n", (double) err[0]);CHKERRQ(ierr); 1784f017bcb6SMatthew G. Knepley } 1785f017bcb6SMatthew G. Knepley } 1786f3c94560SMatthew G. Knepley ierr = PetscFree3(exacts, ectxs, err);CHKERRQ(ierr); 1787f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1788f017bcb6SMatthew G. Knepley } 1789f017bcb6SMatthew G. Knepley 1790f017bcb6SMatthew G. Knepley /*@C 1791f017bcb6SMatthew G. Knepley DMSNESCheckResidual - Check the residual of the exact solution 1792f017bcb6SMatthew G. Knepley 1793f017bcb6SMatthew G. Knepley Input Parameters: 1794f017bcb6SMatthew G. Knepley + snes - the SNES object 1795f017bcb6SMatthew G. Knepley . dm - the DM 1796f017bcb6SMatthew G. Knepley . u - a DM vector 1797f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1798f017bcb6SMatthew G. Knepley 1799f3c94560SMatthew G. Knepley Output Parameters: 1800f3c94560SMatthew G. Knepley . residual - The residual norm of the exact solution, or NULL 1801f3c94560SMatthew G. Knepley 1802f017bcb6SMatthew G. Knepley Level: developer 1803f017bcb6SMatthew G. Knepley 1804f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckJacobian() 1805f017bcb6SMatthew G. Knepley @*/ 1806f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckResidual(SNES snes, DM dm, Vec u, PetscReal tol, PetscReal *residual) 1807f017bcb6SMatthew G. Knepley { 1808f017bcb6SMatthew G. Knepley MPI_Comm comm; 1809f017bcb6SMatthew G. Knepley Vec r; 1810f017bcb6SMatthew G. Knepley PetscReal res; 1811f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1812f017bcb6SMatthew G. Knepley 1813f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1814f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1815f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1816f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1817534a8f05SLisandro Dalcin if (residual) PetscValidRealPointer(residual, 5); 1818f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1819f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr); 1820f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &r);CHKERRQ(ierr); 18211878804aSMatthew G. Knepley ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); 18221878804aSMatthew G. Knepley ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); 1823f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 18242c71b3e2SJacob Faibussowitsch PetscCheckFalse(res > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Residual %g exceeds tolerance %g", (double) res, (double) tol); 1825b878532fSMatthew G. Knepley } else if (residual) { 1826b878532fSMatthew G. Knepley *residual = res; 1827f017bcb6SMatthew G. Knepley } else { 1828f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr); 18291878804aSMatthew G. Knepley ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); 18301878804aSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr); 1831685405a1SBarry Smith ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr); 1832685405a1SBarry Smith ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr); 1833f017bcb6SMatthew G. Knepley } 1834f017bcb6SMatthew G. Knepley ierr = VecDestroy(&r);CHKERRQ(ierr); 1835f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1836f017bcb6SMatthew G. Knepley } 1837f017bcb6SMatthew G. Knepley 1838f017bcb6SMatthew G. Knepley /*@C 1839f3c94560SMatthew G. Knepley DMSNESCheckJacobian - Check the Jacobian of the exact solution against the residual using the Taylor Test 1840f017bcb6SMatthew G. Knepley 1841f017bcb6SMatthew G. Knepley Input Parameters: 1842f017bcb6SMatthew G. Knepley + snes - the SNES object 1843f017bcb6SMatthew G. Knepley . dm - the DM 1844f017bcb6SMatthew G. Knepley . u - a DM vector 1845f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1846f017bcb6SMatthew G. Knepley 1847f3c94560SMatthew G. Knepley Output Parameters: 1848f3c94560SMatthew G. Knepley + isLinear - Flag indicaing that the function looks linear, or NULL 1849f3c94560SMatthew G. Knepley - convRate - The rate of convergence of the linear model, or NULL 1850f3c94560SMatthew G. Knepley 1851f017bcb6SMatthew G. Knepley Level: developer 1852f017bcb6SMatthew G. Knepley 1853f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckResidual() 1854f017bcb6SMatthew G. Knepley @*/ 1855f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckJacobian(SNES snes, DM dm, Vec u, PetscReal tol, PetscBool *isLinear, PetscReal *convRate) 1856f017bcb6SMatthew G. Knepley { 1857f017bcb6SMatthew G. Knepley MPI_Comm comm; 1858f017bcb6SMatthew G. Knepley PetscDS ds; 1859f017bcb6SMatthew G. Knepley Mat J, M; 1860f017bcb6SMatthew G. Knepley MatNullSpace nullspace; 1861f3c94560SMatthew G. Knepley PetscReal slope, intercept; 18627f96f943SMatthew G. Knepley PetscBool hasJac, hasPrec, isLin = PETSC_FALSE; 1863f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1864f017bcb6SMatthew G. Knepley 1865f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1866f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1867f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1868f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1869534a8f05SLisandro Dalcin if (isLinear) PetscValidBoolPointer(isLinear, 5); 1870064a246eSJacob Faibussowitsch if (convRate) PetscValidRealPointer(convRate, 6); 1871f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1872f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr); 1873f017bcb6SMatthew G. Knepley /* Create and view matrices */ 1874f017bcb6SMatthew G. Knepley ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr); 18757f96f943SMatthew G. Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 1876f017bcb6SMatthew G. Knepley ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr); 1877f017bcb6SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr); 1878282e7bb4SMatthew G. Knepley if (hasJac && hasPrec) { 1879282e7bb4SMatthew G. Knepley ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr); 1880282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr); 1881f017bcb6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) M, "Preconditioning Matrix");CHKERRQ(ierr); 1882282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr); 1883282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr); 1884282e7bb4SMatthew G. Knepley ierr = MatDestroy(&M);CHKERRQ(ierr); 1885282e7bb4SMatthew G. Knepley } else { 1886282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr); 1887282e7bb4SMatthew G. Knepley } 1888f017bcb6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) J, "Jacobian");CHKERRQ(ierr); 1889282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr); 1890282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr); 1891f017bcb6SMatthew G. Knepley /* Check nullspace */ 1892f017bcb6SMatthew G. Knepley ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr); 1893f017bcb6SMatthew G. Knepley if (nullspace) { 18941878804aSMatthew G. Knepley PetscBool isNull; 1895f017bcb6SMatthew G. Knepley ierr = MatNullSpaceTest(nullspace, J, &isNull);CHKERRQ(ierr); 18962c71b3e2SJacob Faibussowitsch PetscCheckFalse(!isNull,comm, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid."); 18971878804aSMatthew G. Knepley } 1898f017bcb6SMatthew G. Knepley /* Taylor test */ 1899f017bcb6SMatthew G. Knepley { 1900f017bcb6SMatthew G. Knepley PetscRandom rand; 1901f017bcb6SMatthew G. Knepley Vec du, uhat, r, rhat, df; 1902f3c94560SMatthew G. Knepley PetscReal h; 1903f017bcb6SMatthew G. Knepley PetscReal *es, *hs, *errors; 1904f017bcb6SMatthew G. Knepley PetscReal hMax = 1.0, hMin = 1e-6, hMult = 0.1; 1905f017bcb6SMatthew G. Knepley PetscInt Nv, v; 1906f017bcb6SMatthew G. Knepley 1907f017bcb6SMatthew G. Knepley /* Choose a perturbation direction */ 1908f017bcb6SMatthew G. Knepley ierr = PetscRandomCreate(comm, &rand);CHKERRQ(ierr); 1909f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &du);CHKERRQ(ierr); 1910f017bcb6SMatthew G. Knepley ierr = VecSetRandom(du, rand);CHKERRQ(ierr); 1911f017bcb6SMatthew G. Knepley ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr); 1912f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &df);CHKERRQ(ierr); 1913f017bcb6SMatthew G. Knepley ierr = MatMult(J, du, df);CHKERRQ(ierr); 1914f017bcb6SMatthew G. Knepley /* Evaluate residual at u, F(u), save in vector r */ 1915f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &r);CHKERRQ(ierr); 1916f017bcb6SMatthew G. Knepley ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); 1917f017bcb6SMatthew G. Knepley /* Look at the convergence of our Taylor approximation as we approach u */ 1918f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv); 1919f017bcb6SMatthew G. Knepley ierr = PetscCalloc3(Nv, &es, Nv, &hs, Nv, &errors);CHKERRQ(ierr); 1920f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &uhat);CHKERRQ(ierr); 1921f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &rhat);CHKERRQ(ierr); 1922f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv) { 1923f017bcb6SMatthew G. Knepley ierr = VecWAXPY(uhat, h, du, u);CHKERRQ(ierr); 1924f017bcb6SMatthew G. Knepley /* F(\hat u) \approx F(u) + J(u) (uhat - u) = F(u) + h * J(u) du */ 1925f017bcb6SMatthew G. Knepley ierr = SNESComputeFunction(snes, uhat, rhat);CHKERRQ(ierr); 1926f017bcb6SMatthew G. Knepley ierr = VecAXPBYPCZ(rhat, -1.0, -h, 1.0, r, df);CHKERRQ(ierr); 1927f017bcb6SMatthew G. Knepley ierr = VecNorm(rhat, NORM_2, &errors[Nv]);CHKERRQ(ierr); 1928f017bcb6SMatthew G. Knepley 1929f017bcb6SMatthew G. Knepley es[Nv] = PetscLog10Real(errors[Nv]); 1930f017bcb6SMatthew G. Knepley hs[Nv] = PetscLog10Real(h); 1931f017bcb6SMatthew G. Knepley } 1932f017bcb6SMatthew G. Knepley ierr = VecDestroy(&uhat);CHKERRQ(ierr); 1933f017bcb6SMatthew G. Knepley ierr = VecDestroy(&rhat);CHKERRQ(ierr); 1934f017bcb6SMatthew G. Knepley ierr = VecDestroy(&df);CHKERRQ(ierr); 19351878804aSMatthew G. Knepley ierr = VecDestroy(&r);CHKERRQ(ierr); 1936f017bcb6SMatthew G. Knepley ierr = VecDestroy(&du);CHKERRQ(ierr); 1937f017bcb6SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1938f017bcb6SMatthew G. Knepley if ((tol >= 0) && (errors[v] > tol)) break; 1939f017bcb6SMatthew G. Knepley else if (errors[v] > PETSC_SMALL) break; 1940f017bcb6SMatthew G. Knepley } 1941f3c94560SMatthew G. Knepley if (v == Nv) isLin = PETSC_TRUE; 1942f017bcb6SMatthew G. Knepley ierr = PetscLinearRegression(Nv, hs, es, &slope, &intercept);CHKERRQ(ierr); 1943f017bcb6SMatthew G. Knepley ierr = PetscFree3(es, hs, errors);CHKERRQ(ierr); 1944f017bcb6SMatthew G. Knepley /* Slope should be about 2 */ 1945f017bcb6SMatthew G. Knepley if (tol >= 0) { 19462c71b3e2SJacob Faibussowitsch PetscCheckFalse(!isLin && PetscAbsReal(2 - slope) > tol,comm, PETSC_ERR_ARG_WRONG, "Taylor approximation convergence rate should be 2, not %0.2f", (double) slope); 1947b878532fSMatthew G. Knepley } else if (isLinear || convRate) { 1948b878532fSMatthew G. Knepley if (isLinear) *isLinear = isLin; 1949b878532fSMatthew G. Knepley if (convRate) *convRate = slope; 1950f017bcb6SMatthew G. Knepley } else { 1951f3c94560SMatthew G. Knepley if (!isLin) {ierr = PetscPrintf(comm, "Taylor approximation converging at order %3.2f\n", (double) slope);CHKERRQ(ierr);} 1952f017bcb6SMatthew G. Knepley else {ierr = PetscPrintf(comm, "Function appears to be linear\n");CHKERRQ(ierr);} 1953f017bcb6SMatthew G. Knepley } 1954f017bcb6SMatthew G. Knepley } 19551878804aSMatthew G. Knepley ierr = MatDestroy(&J);CHKERRQ(ierr); 19561878804aSMatthew G. Knepley PetscFunctionReturn(0); 19571878804aSMatthew G. Knepley } 19581878804aSMatthew G. Knepley 19597f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheck_Internal(SNES snes, DM dm, Vec u) 1960f017bcb6SMatthew G. Knepley { 1961f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1962f017bcb6SMatthew G. Knepley 1963f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1964f2cacb80SMatthew G. Knepley ierr = DMSNESCheckDiscretization(snes, dm, 0.0, u, -1.0, NULL);CHKERRQ(ierr); 1965f3c94560SMatthew G. Knepley ierr = DMSNESCheckResidual(snes, dm, u, -1.0, NULL);CHKERRQ(ierr); 1966f3c94560SMatthew G. Knepley ierr = DMSNESCheckJacobian(snes, dm, u, -1.0, NULL, NULL);CHKERRQ(ierr); 1967f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1968f017bcb6SMatthew G. Knepley } 1969f017bcb6SMatthew G. Knepley 1970bee9a294SMatthew G. Knepley /*@C 1971bee9a294SMatthew G. Knepley DMSNESCheckFromOptions - Check the residual and Jacobian functions using the exact solution by outputting some diagnostic information 1972bee9a294SMatthew G. Knepley 1973bee9a294SMatthew G. Knepley Input Parameters: 1974bee9a294SMatthew G. Knepley + snes - the SNES object 19757f96f943SMatthew G. Knepley - u - representative SNES vector 19767f96f943SMatthew G. Knepley 19777f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 1978bee9a294SMatthew G. Knepley 1979bee9a294SMatthew G. Knepley Level: developer 1980bee9a294SMatthew G. Knepley @*/ 19817f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u) 19821878804aSMatthew G. Knepley { 19831878804aSMatthew G. Knepley DM dm; 19841878804aSMatthew G. Knepley Vec sol; 19851878804aSMatthew G. Knepley PetscBool check; 19861878804aSMatthew G. Knepley PetscErrorCode ierr; 19871878804aSMatthew G. Knepley 19881878804aSMatthew G. Knepley PetscFunctionBegin; 1989c5929fdfSBarry Smith ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr); 19901878804aSMatthew G. Knepley if (!check) PetscFunctionReturn(0); 19911878804aSMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 19921878804aSMatthew G. Knepley ierr = VecDuplicate(u, &sol);CHKERRQ(ierr); 19931878804aSMatthew G. Knepley ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr); 19947f96f943SMatthew G. Knepley ierr = DMSNESCheck_Internal(snes, dm, sol);CHKERRQ(ierr); 19951878804aSMatthew G. Knepley ierr = VecDestroy(&sol);CHKERRQ(ierr); 1996552f7358SJed Brown PetscFunctionReturn(0); 1997552f7358SJed Brown } 1998