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); 509ace16cdSJacob Faibussowitsch PetscAssertFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a SNES DM"); 519ace16cdSJacob Faibussowitsch PetscAssertFalse(!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); 559ace16cdSJacob Faibussowitsch PetscAssertFalse(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); 579ace16cdSJacob Faibussowitsch PetscAssertFalse(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); 659ace16cdSJacob Faibussowitsch PetscAssertFalse(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; 2069ace16cdSJacob Faibussowitsch PetscAssertFalse((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; 2509ace16cdSJacob Faibussowitsch PetscAssertFalse(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; 2999ace16cdSJacob Faibussowitsch PetscAssertFalse(ctx->dim < 0,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 3009ace16cdSJacob Faibussowitsch PetscAssertFalse(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); 3469ace16cdSJacob Faibussowitsch PetscAssertFalse(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) { 3949ace16cdSJacob Faibussowitsch PetscAssertFalse(!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); 4569ace16cdSJacob Faibussowitsch PetscAssertFalse(!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); 4849ace16cdSJacob Faibussowitsch PetscAssertFalse(!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); 5119ace16cdSJacob Faibussowitsch PetscAssertFalse(!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*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 517a6dfd86eSKarl Rupp { 518552f7358SJed Brown PetscReal *v0, *J, *invJ, detJ; 51956044e6dSMatthew G. Knepley const PetscScalar *coords; 52056044e6dSMatthew G. Knepley PetscScalar *a; 521552f7358SJed Brown PetscInt p; 522552f7358SJed Brown PetscErrorCode ierr; 523552f7358SJed Brown 524552f7358SJed Brown PetscFunctionBegin; 525dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 52656044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 527552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 528552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 529552f7358SJed Brown PetscInt c = ctx->cells[p]; 530a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 531552f7358SJed Brown PetscReal xi[4]; 532552f7358SJed Brown PetscInt d, f, comp; 533552f7358SJed Brown 5348e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 5359ace16cdSJacob Faibussowitsch PetscAssertFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 5360298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 5371aa26658SKarl Rupp for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 5381aa26658SKarl Rupp 539552f7358SJed Brown for (d = 0; d < ctx->dim; ++d) { 540552f7358SJed Brown xi[d] = 0.0; 5411aa26658SKarl 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]); 5421aa26658SKarl 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]; 543552f7358SJed Brown } 5440298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 545552f7358SJed Brown } 546552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 54756044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 548552f7358SJed Brown ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 549552f7358SJed Brown PetscFunctionReturn(0); 550552f7358SJed Brown } 551552f7358SJed Brown 552*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 5537a1931ceSMatthew G. Knepley { 5547a1931ceSMatthew G. Knepley PetscReal *v0, *J, *invJ, detJ; 55556044e6dSMatthew G. Knepley const PetscScalar *coords; 55656044e6dSMatthew G. Knepley PetscScalar *a; 5577a1931ceSMatthew G. Knepley PetscInt p; 5587a1931ceSMatthew G. Knepley PetscErrorCode ierr; 5597a1931ceSMatthew G. Knepley 5607a1931ceSMatthew G. Knepley PetscFunctionBegin; 561dcca6d9dSJed Brown ierr = PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ);CHKERRQ(ierr); 56256044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 5637a1931ceSMatthew G. Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 5647a1931ceSMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 5657a1931ceSMatthew G. Knepley PetscInt c = ctx->cells[p]; 5667a1931ceSMatthew G. Knepley const PetscInt order[3] = {2, 1, 3}; 5672584bbe8SMatthew G. Knepley PetscScalar *x = NULL; 5687a1931ceSMatthew G. Knepley PetscReal xi[4]; 5697a1931ceSMatthew G. Knepley PetscInt d, f, comp; 5707a1931ceSMatthew G. Knepley 5718e0841e0SMatthew G. Knepley ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 5729ace16cdSJacob Faibussowitsch PetscAssertFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 5737a1931ceSMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 5747a1931ceSMatthew G. Knepley for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 5757a1931ceSMatthew G. Knepley 5767a1931ceSMatthew G. Knepley for (d = 0; d < ctx->dim; ++d) { 5777a1931ceSMatthew G. Knepley xi[d] = 0.0; 5787a1931ceSMatthew 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]); 5797a1931ceSMatthew 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]; 5807a1931ceSMatthew G. Knepley } 5817a1931ceSMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x);CHKERRQ(ierr); 5827a1931ceSMatthew G. Knepley } 5837a1931ceSMatthew G. Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 58456044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 5857a1931ceSMatthew G. Knepley ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr); 5867a1931ceSMatthew G. Knepley PetscFunctionReturn(0); 5877a1931ceSMatthew G. Knepley } 5887a1931ceSMatthew G. Knepley 589*9fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 590552f7358SJed Brown { 591552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 592552f7358SJed Brown const PetscScalar x0 = vertices[0]; 593552f7358SJed Brown const PetscScalar y0 = vertices[1]; 594552f7358SJed Brown const PetscScalar x1 = vertices[2]; 595552f7358SJed Brown const PetscScalar y1 = vertices[3]; 596552f7358SJed Brown const PetscScalar x2 = vertices[4]; 597552f7358SJed Brown const PetscScalar y2 = vertices[5]; 598552f7358SJed Brown const PetscScalar x3 = vertices[6]; 599552f7358SJed Brown const PetscScalar y3 = vertices[7]; 600552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 601552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 602552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 603552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 604552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 605552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 60656044e6dSMatthew G. Knepley const PetscScalar *ref; 60756044e6dSMatthew G. Knepley PetscScalar *real; 608552f7358SJed Brown PetscErrorCode ierr; 609552f7358SJed Brown 610552f7358SJed Brown PetscFunctionBegin; 61156044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 612552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 613552f7358SJed Brown { 614552f7358SJed Brown const PetscScalar p0 = ref[0]; 615552f7358SJed Brown const PetscScalar p1 = ref[1]; 616552f7358SJed Brown 617552f7358SJed Brown real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1; 618552f7358SJed Brown real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1; 619552f7358SJed Brown } 620552f7358SJed Brown ierr = PetscLogFlops(28);CHKERRQ(ierr); 62156044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 622552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 623552f7358SJed Brown PetscFunctionReturn(0); 624552f7358SJed Brown } 625552f7358SJed Brown 626af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 627*9fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 628552f7358SJed Brown { 629552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 630552f7358SJed Brown const PetscScalar x0 = vertices[0]; 631552f7358SJed Brown const PetscScalar y0 = vertices[1]; 632552f7358SJed Brown const PetscScalar x1 = vertices[2]; 633552f7358SJed Brown const PetscScalar y1 = vertices[3]; 634552f7358SJed Brown const PetscScalar x2 = vertices[4]; 635552f7358SJed Brown const PetscScalar y2 = vertices[5]; 636552f7358SJed Brown const PetscScalar x3 = vertices[6]; 637552f7358SJed Brown const PetscScalar y3 = vertices[7]; 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; 641552f7358SJed Brown PetscErrorCode ierr; 642552f7358SJed Brown 643552f7358SJed Brown PetscFunctionBegin; 64456044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 645552f7358SJed Brown { 646552f7358SJed Brown const PetscScalar x = ref[0]; 647552f7358SJed Brown const PetscScalar y = ref[1]; 648552f7358SJed Brown const PetscInt rows[2] = {0, 1}; 649da80777bSKarl Rupp PetscScalar values[4]; 650da80777bSKarl Rupp 651da80777bSKarl Rupp values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5; 652da80777bSKarl Rupp values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5; 65394ab13aaSBarry Smith ierr = MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES);CHKERRQ(ierr); 654552f7358SJed Brown } 655552f7358SJed Brown ierr = PetscLogFlops(30);CHKERRQ(ierr); 65656044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 65794ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 65894ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 659552f7358SJed Brown PetscFunctionReturn(0); 660552f7358SJed Brown } 661552f7358SJed Brown 662*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 663a6dfd86eSKarl Rupp { 664fafc0619SMatthew G Knepley DM dmCoord; 665de73a395SMatthew G. Knepley PetscFE fem = NULL; 666552f7358SJed Brown SNES snes; 667552f7358SJed Brown KSP ksp; 668552f7358SJed Brown PC pc; 669552f7358SJed Brown Vec coordsLocal, r, ref, real; 670552f7358SJed Brown Mat J; 671716009bfSMatthew G. Knepley PetscTabulation T = NULL; 67256044e6dSMatthew G. Knepley const PetscScalar *coords; 67356044e6dSMatthew G. Knepley PetscScalar *a; 674716009bfSMatthew G. Knepley PetscReal xir[2] = {0., 0.}; 675de73a395SMatthew G. Knepley PetscInt Nf, p; 6765509d985SMatthew G. Knepley const PetscInt dof = ctx->dof; 677552f7358SJed Brown PetscErrorCode ierr; 678552f7358SJed Brown 679552f7358SJed Brown PetscFunctionBegin; 680de73a395SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 681716009bfSMatthew G. Knepley if (Nf) { 682716009bfSMatthew G. Knepley ierr = DMGetField(dm, 0, NULL, (PetscObject *) &fem);CHKERRQ(ierr); 683716009bfSMatthew G. Knepley ierr = PetscFECreateTabulation(fem, 1, 1, xir, 0, &T);CHKERRQ(ierr); 684716009bfSMatthew G. Knepley } 685552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 686fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 687552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 688552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "quad_interp_");CHKERRQ(ierr); 689552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 690552f7358SJed Brown ierr = VecSetSizes(r, 2, 2);CHKERRQ(ierr); 691c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 692552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 693552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 694552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 695552f7358SJed Brown ierr = MatSetSizes(J, 2, 2, 2, 2);CHKERRQ(ierr); 696552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 697552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 6980298fd71SBarry Smith ierr = SNESSetFunction(snes, r, QuadMap_Private, NULL);CHKERRQ(ierr); 6990298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL);CHKERRQ(ierr); 700552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 701552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 702552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 703552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 704552f7358SJed Brown 70556044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 706552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 707552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 708a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 709552f7358SJed Brown PetscScalar *xi; 710552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 711552f7358SJed Brown 712552f7358SJed Brown /* Can make this do all points at once */ 7130298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 7149ace16cdSJacob Faibussowitsch PetscAssertFalse(4*2 != coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 4*2); 7150298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 7163ec1f749SStefano Zampini ierr = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr); 7173ec1f749SStefano Zampini ierr = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr); 718552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 719552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 720552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 721552f7358SJed Brown ierr = VecRestoreArray(real, &xi);CHKERRQ(ierr); 722552f7358SJed Brown ierr = SNESSolve(snes, real, ref);CHKERRQ(ierr); 723552f7358SJed Brown ierr = VecGetArray(ref, &xi);CHKERRQ(ierr); 724cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 725cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 7265509d985SMatthew G. Knepley if (4*dof != xSize) { 7275509d985SMatthew G. Knepley PetscInt d; 7281aa26658SKarl Rupp 7299ace16cdSJacob Faibussowitsch PetscAssert(fem, ctx->comm, PETSC_ERR_ARG_WRONG, "Cannot have a higher order interpolant if the discretization is not PetscFE"); 7305509d985SMatthew G. Knepley xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0; 731ef0bb6c7SMatthew G. Knepley ierr = PetscFEComputeTabulation(fem, 1, xir, 0, T);CHKERRQ(ierr); 7325509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) { 7335509d985SMatthew G. Knepley a[p*dof+comp] = 0.0; 7345509d985SMatthew G. Knepley for (d = 0; d < xSize/dof; ++d) { 735ef0bb6c7SMatthew G. Knepley a[p*dof+comp] += x[d*dof+comp]*T->T[0][d*dof+comp]; 7365509d985SMatthew G. Knepley } 7375509d985SMatthew G. Knepley } 7385509d985SMatthew G. Knepley } else { 7395509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) 7405509d985SMatthew 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]; 7415509d985SMatthew G. Knepley } 742552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 7430298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 7440298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 745552f7358SJed Brown } 746ef0bb6c7SMatthew G. Knepley ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr); 747552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 74856044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 749552f7358SJed Brown 750552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 751552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 752552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 753552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 754552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 755552f7358SJed Brown PetscFunctionReturn(0); 756552f7358SJed Brown } 757552f7358SJed Brown 758*9fbee547SJacob Faibussowitsch static inline PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 759552f7358SJed Brown { 760552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 761552f7358SJed Brown const PetscScalar x0 = vertices[0]; 762552f7358SJed Brown const PetscScalar y0 = vertices[1]; 763552f7358SJed Brown const PetscScalar z0 = vertices[2]; 7647a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 7657a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 7667a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 767552f7358SJed Brown const PetscScalar x2 = vertices[6]; 768552f7358SJed Brown const PetscScalar y2 = vertices[7]; 769552f7358SJed Brown const PetscScalar z2 = vertices[8]; 7707a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 7717a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 7727a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 773552f7358SJed Brown const PetscScalar x4 = vertices[12]; 774552f7358SJed Brown const PetscScalar y4 = vertices[13]; 775552f7358SJed Brown const PetscScalar z4 = vertices[14]; 776552f7358SJed Brown const PetscScalar x5 = vertices[15]; 777552f7358SJed Brown const PetscScalar y5 = vertices[16]; 778552f7358SJed Brown const PetscScalar z5 = vertices[17]; 779552f7358SJed Brown const PetscScalar x6 = vertices[18]; 780552f7358SJed Brown const PetscScalar y6 = vertices[19]; 781552f7358SJed Brown const PetscScalar z6 = vertices[20]; 782552f7358SJed Brown const PetscScalar x7 = vertices[21]; 783552f7358SJed Brown const PetscScalar y7 = vertices[22]; 784552f7358SJed Brown const PetscScalar z7 = vertices[23]; 785552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 786552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 787552f7358SJed Brown const PetscScalar h_1 = z1 - z0; 788552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 789552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 790552f7358SJed Brown const PetscScalar h_3 = z3 - z0; 791552f7358SJed Brown const PetscScalar f_4 = x4 - x0; 792552f7358SJed Brown const PetscScalar g_4 = y4 - y0; 793552f7358SJed Brown const PetscScalar h_4 = z4 - z0; 794552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 795552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 796552f7358SJed Brown const PetscScalar h_01 = z2 - z1 - z3 + z0; 797552f7358SJed Brown const PetscScalar f_12 = x7 - x3 - x4 + x0; 798552f7358SJed Brown const PetscScalar g_12 = y7 - y3 - y4 + y0; 799552f7358SJed Brown const PetscScalar h_12 = z7 - z3 - z4 + z0; 800552f7358SJed Brown const PetscScalar f_02 = x5 - x1 - x4 + x0; 801552f7358SJed Brown const PetscScalar g_02 = y5 - y1 - y4 + y0; 802552f7358SJed Brown const PetscScalar h_02 = z5 - z1 - z4 + z0; 803552f7358SJed Brown const PetscScalar f_012 = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 804552f7358SJed Brown const PetscScalar g_012 = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 805552f7358SJed Brown const PetscScalar h_012 = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 80656044e6dSMatthew G. Knepley const PetscScalar *ref; 80756044e6dSMatthew G. Knepley PetscScalar *real; 808552f7358SJed Brown PetscErrorCode ierr; 809552f7358SJed Brown 810552f7358SJed Brown PetscFunctionBegin; 81156044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 812552f7358SJed Brown ierr = VecGetArray(Xreal, &real);CHKERRQ(ierr); 813552f7358SJed Brown { 814552f7358SJed Brown const PetscScalar p0 = ref[0]; 815552f7358SJed Brown const PetscScalar p1 = ref[1]; 816552f7358SJed Brown const PetscScalar p2 = ref[2]; 817552f7358SJed Brown 818552f7358SJed 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; 819552f7358SJed 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; 820552f7358SJed 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; 821552f7358SJed Brown } 822552f7358SJed Brown ierr = PetscLogFlops(114);CHKERRQ(ierr); 82356044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 824552f7358SJed Brown ierr = VecRestoreArray(Xreal, &real);CHKERRQ(ierr); 825552f7358SJed Brown PetscFunctionReturn(0); 826552f7358SJed Brown } 827552f7358SJed Brown 828*9fbee547SJacob Faibussowitsch static inline PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 829552f7358SJed Brown { 830552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 831552f7358SJed Brown const PetscScalar x0 = vertices[0]; 832552f7358SJed Brown const PetscScalar y0 = vertices[1]; 833552f7358SJed Brown const PetscScalar z0 = vertices[2]; 8347a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 8357a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 8367a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 837552f7358SJed Brown const PetscScalar x2 = vertices[6]; 838552f7358SJed Brown const PetscScalar y2 = vertices[7]; 839552f7358SJed Brown const PetscScalar z2 = vertices[8]; 8407a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 8417a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 8427a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 843552f7358SJed Brown const PetscScalar x4 = vertices[12]; 844552f7358SJed Brown const PetscScalar y4 = vertices[13]; 845552f7358SJed Brown const PetscScalar z4 = vertices[14]; 846552f7358SJed Brown const PetscScalar x5 = vertices[15]; 847552f7358SJed Brown const PetscScalar y5 = vertices[16]; 848552f7358SJed Brown const PetscScalar z5 = vertices[17]; 849552f7358SJed Brown const PetscScalar x6 = vertices[18]; 850552f7358SJed Brown const PetscScalar y6 = vertices[19]; 851552f7358SJed Brown const PetscScalar z6 = vertices[20]; 852552f7358SJed Brown const PetscScalar x7 = vertices[21]; 853552f7358SJed Brown const PetscScalar y7 = vertices[22]; 854552f7358SJed Brown const PetscScalar z7 = vertices[23]; 855552f7358SJed Brown const PetscScalar f_xy = x2 - x1 - x3 + x0; 856552f7358SJed Brown const PetscScalar g_xy = y2 - y1 - y3 + y0; 857552f7358SJed Brown const PetscScalar h_xy = z2 - z1 - z3 + z0; 858552f7358SJed Brown const PetscScalar f_yz = x7 - x3 - x4 + x0; 859552f7358SJed Brown const PetscScalar g_yz = y7 - y3 - y4 + y0; 860552f7358SJed Brown const PetscScalar h_yz = z7 - z3 - z4 + z0; 861552f7358SJed Brown const PetscScalar f_xz = x5 - x1 - x4 + x0; 862552f7358SJed Brown const PetscScalar g_xz = y5 - y1 - y4 + y0; 863552f7358SJed Brown const PetscScalar h_xz = z5 - z1 - z4 + z0; 864552f7358SJed Brown const PetscScalar f_xyz = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 865552f7358SJed Brown const PetscScalar g_xyz = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 866552f7358SJed Brown const PetscScalar h_xyz = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 86756044e6dSMatthew G. Knepley const PetscScalar *ref; 868552f7358SJed Brown PetscErrorCode ierr; 869552f7358SJed Brown 870552f7358SJed Brown PetscFunctionBegin; 87156044e6dSMatthew G. Knepley ierr = VecGetArrayRead(Xref, &ref);CHKERRQ(ierr); 872552f7358SJed Brown { 873552f7358SJed Brown const PetscScalar x = ref[0]; 874552f7358SJed Brown const PetscScalar y = ref[1]; 875552f7358SJed Brown const PetscScalar z = ref[2]; 876552f7358SJed Brown const PetscInt rows[3] = {0, 1, 2}; 877da80777bSKarl Rupp PetscScalar values[9]; 878da80777bSKarl Rupp 879da80777bSKarl Rupp values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0; 880da80777bSKarl Rupp values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0; 881da80777bSKarl Rupp values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0; 882da80777bSKarl Rupp values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0; 883da80777bSKarl Rupp values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0; 884da80777bSKarl Rupp values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0; 885da80777bSKarl Rupp values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0; 886da80777bSKarl Rupp values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0; 887da80777bSKarl Rupp values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0; 8881aa26658SKarl Rupp 88994ab13aaSBarry Smith ierr = MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES);CHKERRQ(ierr); 890552f7358SJed Brown } 891552f7358SJed Brown ierr = PetscLogFlops(152);CHKERRQ(ierr); 89256044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(Xref, &ref);CHKERRQ(ierr); 89394ab13aaSBarry Smith ierr = MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 89494ab13aaSBarry Smith ierr = MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 895552f7358SJed Brown PetscFunctionReturn(0); 896552f7358SJed Brown } 897552f7358SJed Brown 898*9fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 899a6dfd86eSKarl Rupp { 900fafc0619SMatthew G Knepley DM dmCoord; 901552f7358SJed Brown SNES snes; 902552f7358SJed Brown KSP ksp; 903552f7358SJed Brown PC pc; 904552f7358SJed Brown Vec coordsLocal, r, ref, real; 905552f7358SJed Brown Mat J; 90656044e6dSMatthew G. Knepley const PetscScalar *coords; 90756044e6dSMatthew G. Knepley PetscScalar *a; 908552f7358SJed Brown PetscInt p; 909552f7358SJed Brown PetscErrorCode ierr; 910552f7358SJed Brown 911552f7358SJed Brown PetscFunctionBegin; 912552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 913fafc0619SMatthew G Knepley ierr = DMGetCoordinateDM(dm, &dmCoord);CHKERRQ(ierr); 914552f7358SJed Brown ierr = SNESCreate(PETSC_COMM_SELF, &snes);CHKERRQ(ierr); 915552f7358SJed Brown ierr = SNESSetOptionsPrefix(snes, "hex_interp_");CHKERRQ(ierr); 916552f7358SJed Brown ierr = VecCreate(PETSC_COMM_SELF, &r);CHKERRQ(ierr); 917552f7358SJed Brown ierr = VecSetSizes(r, 3, 3);CHKERRQ(ierr); 918c0dedaeaSBarry Smith ierr = VecSetType(r,dm->vectype);CHKERRQ(ierr); 919552f7358SJed Brown ierr = VecDuplicate(r, &ref);CHKERRQ(ierr); 920552f7358SJed Brown ierr = VecDuplicate(r, &real);CHKERRQ(ierr); 921552f7358SJed Brown ierr = MatCreate(PETSC_COMM_SELF, &J);CHKERRQ(ierr); 922552f7358SJed Brown ierr = MatSetSizes(J, 3, 3, 3, 3);CHKERRQ(ierr); 923552f7358SJed Brown ierr = MatSetType(J, MATSEQDENSE);CHKERRQ(ierr); 924552f7358SJed Brown ierr = MatSetUp(J);CHKERRQ(ierr); 9250298fd71SBarry Smith ierr = SNESSetFunction(snes, r, HexMap_Private, NULL);CHKERRQ(ierr); 9260298fd71SBarry Smith ierr = SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL);CHKERRQ(ierr); 927552f7358SJed Brown ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); 928552f7358SJed Brown ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 929552f7358SJed Brown ierr = PCSetType(pc, PCLU);CHKERRQ(ierr); 930552f7358SJed Brown ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 931552f7358SJed Brown 93256044e6dSMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 933552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 934552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 935a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 936552f7358SJed Brown PetscScalar *xi; 937cb313848SJed Brown PetscReal xir[3]; 938552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 939552f7358SJed Brown 940552f7358SJed Brown /* Can make this do all points at once */ 9410298fd71SBarry Smith ierr = DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 9429ace16cdSJacob Faibussowitsch PetscAssertFalse(8*3 != coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 8*3); 9430298fd71SBarry Smith ierr = DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 9449ace16cdSJacob Faibussowitsch PetscAssertFalse(8*ctx->dof != xSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %D", xSize, 8*ctx->dof); 9453ec1f749SStefano Zampini ierr = SNESSetFunction(snes, NULL, NULL, vertices);CHKERRQ(ierr); 9463ec1f749SStefano Zampini ierr = SNESSetJacobian(snes, NULL, NULL, NULL, vertices);CHKERRQ(ierr); 947552f7358SJed Brown ierr = VecGetArray(real, &xi);CHKERRQ(ierr); 948552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 949552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 950552f7358SJed Brown xi[2] = coords[p*ctx->dim+2]; 951552f7358SJed Brown ierr = VecRestoreArray(real, &xi);CHKERRQ(ierr); 952552f7358SJed Brown ierr = SNESSolve(snes, real, ref);CHKERRQ(ierr); 953552f7358SJed Brown ierr = VecGetArray(ref, &xi);CHKERRQ(ierr); 954cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 955cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 956cb313848SJed Brown xir[2] = PetscRealPart(xi[2]); 957552f7358SJed Brown for (comp = 0; comp < ctx->dof; ++comp) { 958552f7358SJed Brown a[p*ctx->dof+comp] = 959cb313848SJed Brown x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) + 9607a1931ceSMatthew G. Knepley x[3*ctx->dof+comp]* xir[0]*(1-xir[1])*(1-xir[2]) + 961cb313848SJed Brown x[2*ctx->dof+comp]* xir[0]* xir[1]*(1-xir[2]) + 9627a1931ceSMatthew G. Knepley x[1*ctx->dof+comp]*(1-xir[0])* xir[1]*(1-xir[2]) + 963cb313848SJed Brown x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])* xir[2] + 964cb313848SJed Brown x[5*ctx->dof+comp]* xir[0]*(1-xir[1])* xir[2] + 965cb313848SJed Brown x[6*ctx->dof+comp]* xir[0]* xir[1]* xir[2] + 966cb313848SJed Brown x[7*ctx->dof+comp]*(1-xir[0])* xir[1]* xir[2]; 967552f7358SJed Brown } 968552f7358SJed Brown ierr = VecRestoreArray(ref, &xi);CHKERRQ(ierr); 9690298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices);CHKERRQ(ierr); 9700298fd71SBarry Smith ierr = DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x);CHKERRQ(ierr); 971552f7358SJed Brown } 972552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 97356044e6dSMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 974552f7358SJed Brown 975552f7358SJed Brown ierr = SNESDestroy(&snes);CHKERRQ(ierr); 976552f7358SJed Brown ierr = VecDestroy(&r);CHKERRQ(ierr); 977552f7358SJed Brown ierr = VecDestroy(&ref);CHKERRQ(ierr); 978552f7358SJed Brown ierr = VecDestroy(&real);CHKERRQ(ierr); 979552f7358SJed Brown ierr = MatDestroy(&J);CHKERRQ(ierr); 980552f7358SJed Brown PetscFunctionReturn(0); 981552f7358SJed Brown } 982552f7358SJed Brown 9834267b1a3SMatthew G. Knepley /*@C 9844267b1a3SMatthew G. Knepley DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points. 9854267b1a3SMatthew G. Knepley 986552f7358SJed Brown Input Parameters: 987552f7358SJed Brown + ctx - The DMInterpolationInfo context 988552f7358SJed Brown . dm - The DM 989552f7358SJed Brown - x - The local vector containing the field to be interpolated 990552f7358SJed Brown 991552f7358SJed Brown Output Parameters: 992552f7358SJed Brown . v - The vector containing the interpolated values 9934267b1a3SMatthew G. Knepley 9944267b1a3SMatthew G. Knepley Note: A suitable v can be obtained using DMInterpolationGetVector(). 9954267b1a3SMatthew G. Knepley 9964267b1a3SMatthew G. Knepley Level: beginner 9974267b1a3SMatthew G. Knepley 9984267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationAddPoints(), DMInterpolationCreate() 9994267b1a3SMatthew G. Knepley @*/ 10000adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v) 10010adebc6cSBarry Smith { 100266a0a883SMatthew G. Knepley PetscDS ds; 100366a0a883SMatthew G. Knepley PetscInt n, p, Nf, field; 100466a0a883SMatthew G. Knepley PetscBool useDS = PETSC_FALSE; 1005552f7358SJed Brown PetscErrorCode ierr; 1006552f7358SJed Brown 1007552f7358SJed Brown PetscFunctionBegin; 1008552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1009552f7358SJed Brown PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 1010552f7358SJed Brown PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 1011552f7358SJed Brown ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr); 10129ace16cdSJacob Faibussowitsch PetscAssertFalse(n != ctx->n*ctx->dof,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %D should be %D", n, ctx->n*ctx->dof); 101366a0a883SMatthew G. Knepley if (!n) PetscFunctionReturn(0); 1014680d18d5SMatthew G. Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 1015680d18d5SMatthew G. Knepley if (ds) { 101666a0a883SMatthew G. Knepley useDS = PETSC_TRUE; 1017680d18d5SMatthew G. Knepley ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 1018680d18d5SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 101966a0a883SMatthew G. Knepley PetscObject obj; 1020680d18d5SMatthew G. Knepley PetscClassId id; 1021680d18d5SMatthew G. Knepley 102266a0a883SMatthew G. Knepley ierr = PetscDSGetDiscretization(ds, field, &obj);CHKERRQ(ierr); 102366a0a883SMatthew G. Knepley ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 102466a0a883SMatthew G. Knepley if (id != PETSCFE_CLASSID) {useDS = PETSC_FALSE; break;} 102566a0a883SMatthew G. Knepley } 102666a0a883SMatthew G. Knepley } 102766a0a883SMatthew G. Knepley if (useDS) { 102866a0a883SMatthew G. Knepley const PetscScalar *coords; 102966a0a883SMatthew G. Knepley PetscScalar *interpolant; 103066a0a883SMatthew G. Knepley PetscInt cdim, d; 103166a0a883SMatthew G. Knepley 103266a0a883SMatthew G. Knepley ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 1033680d18d5SMatthew G. Knepley ierr = VecGetArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 1034680d18d5SMatthew G. Knepley ierr = VecGetArrayWrite(v, &interpolant);CHKERRQ(ierr); 1035680d18d5SMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 103666a0a883SMatthew G. Knepley PetscReal pcoords[3], xi[3]; 1037680d18d5SMatthew G. Knepley PetscScalar *xa = NULL; 103866a0a883SMatthew G. Knepley PetscInt coff = 0, foff = 0, clSize; 1039680d18d5SMatthew G. Knepley 104052aa1562SMatthew G. Knepley if (ctx->cells[p] < 0) continue; 1041680d18d5SMatthew G. Knepley for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p*cdim+d]); 1042680d18d5SMatthew G. Knepley ierr = DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi);CHKERRQ(ierr); 104366a0a883SMatthew G. Knepley ierr = DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr); 104466a0a883SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 104566a0a883SMatthew G. Knepley PetscTabulation T; 104666a0a883SMatthew G. Knepley PetscFE fe; 104766a0a883SMatthew G. Knepley 104866a0a883SMatthew G. Knepley ierr = PetscDSGetDiscretization(ds, field, (PetscObject *) &fe);CHKERRQ(ierr); 1049680d18d5SMatthew G. Knepley ierr = PetscFECreateTabulation(fe, 1, 1, xi, 0, &T);CHKERRQ(ierr); 1050680d18d5SMatthew G. Knepley { 1051680d18d5SMatthew G. Knepley const PetscReal *basis = T->T[0]; 1052680d18d5SMatthew G. Knepley const PetscInt Nb = T->Nb; 1053680d18d5SMatthew G. Knepley const PetscInt Nc = T->Nc; 105466a0a883SMatthew G. Knepley PetscInt f, fc; 105566a0a883SMatthew G. Knepley 1056680d18d5SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 105766a0a883SMatthew G. Knepley interpolant[p*ctx->dof+coff+fc] = 0.0; 1058680d18d5SMatthew G. Knepley for (f = 0; f < Nb; ++f) { 105966a0a883SMatthew G. Knepley interpolant[p*ctx->dof+coff+fc] += xa[foff+f]*basis[(0*Nb + f)*Nc + fc]; 1060552f7358SJed Brown } 1061680d18d5SMatthew G. Knepley } 106266a0a883SMatthew G. Knepley coff += Nc; 106366a0a883SMatthew G. Knepley foff += Nb; 1064680d18d5SMatthew G. Knepley } 1065680d18d5SMatthew G. Knepley ierr = PetscTabulationDestroy(&T);CHKERRQ(ierr); 1066680d18d5SMatthew G. Knepley } 106766a0a883SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa);CHKERRQ(ierr); 10689ace16cdSJacob Faibussowitsch PetscAssertFalse(coff != ctx->dof,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %D != %D dof specified for interpolation", coff, ctx->dof); 10699ace16cdSJacob Faibussowitsch PetscAssertFalse(foff != clSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total FE space size %D != %D closure size", foff, clSize); 107066a0a883SMatthew G. Knepley } 1071680d18d5SMatthew G. Knepley ierr = VecRestoreArrayRead(ctx->coords, &coords);CHKERRQ(ierr); 107266a0a883SMatthew G. Knepley ierr = VecRestoreArrayWrite(v, &interpolant);CHKERRQ(ierr); 107366a0a883SMatthew G. Knepley } else { 107466a0a883SMatthew G. Knepley DMPolytopeType ct; 107566a0a883SMatthew G. Knepley 1076680d18d5SMatthew G. Knepley /* TODO Check each cell individually */ 1077680d18d5SMatthew G. Knepley ierr = DMPlexGetCellType(dm, ctx->cells[0], &ct);CHKERRQ(ierr); 1078680d18d5SMatthew G. Knepley switch (ct) { 1079680d18d5SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: ierr = DMInterpolate_Triangle_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1080680d18d5SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: ierr = DMInterpolate_Quad_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1081680d18d5SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: ierr = DMInterpolate_Tetrahedron_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 1082680d18d5SMatthew G. Knepley case DM_POLYTOPE_HEXAHEDRON: ierr = DMInterpolate_Hex_Private(ctx, dm, x, v);CHKERRQ(ierr);break; 108398921bdaSJacob Faibussowitsch default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for cell type %s", DMPolytopeTypes[ct]); 1084680d18d5SMatthew G. Knepley } 1085552f7358SJed Brown } 1086552f7358SJed Brown PetscFunctionReturn(0); 1087552f7358SJed Brown } 1088552f7358SJed Brown 10894267b1a3SMatthew G. Knepley /*@C 10904267b1a3SMatthew G. Knepley DMInterpolationDestroy - Destroys a DMInterpolationInfo context 10914267b1a3SMatthew G. Knepley 10924267b1a3SMatthew G. Knepley Collective on ctx 10934267b1a3SMatthew G. Knepley 10944267b1a3SMatthew G. Knepley Input Parameter: 10954267b1a3SMatthew G. Knepley . ctx - the context 10964267b1a3SMatthew G. Knepley 10974267b1a3SMatthew G. Knepley Level: beginner 10984267b1a3SMatthew G. Knepley 10994267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 11004267b1a3SMatthew G. Knepley @*/ 11010adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx) 11020adebc6cSBarry Smith { 1103552f7358SJed Brown PetscErrorCode ierr; 1104552f7358SJed Brown 1105552f7358SJed Brown PetscFunctionBegin; 1106064a246eSJacob Faibussowitsch PetscValidPointer(ctx, 1); 1107552f7358SJed Brown ierr = VecDestroy(&(*ctx)->coords);CHKERRQ(ierr); 1108552f7358SJed Brown ierr = PetscFree((*ctx)->points);CHKERRQ(ierr); 1109552f7358SJed Brown ierr = PetscFree((*ctx)->cells);CHKERRQ(ierr); 1110552f7358SJed Brown ierr = PetscFree(*ctx);CHKERRQ(ierr); 11110298fd71SBarry Smith *ctx = NULL; 1112552f7358SJed Brown PetscFunctionReturn(0); 1113552f7358SJed Brown } 1114cc0c4584SMatthew G. Knepley 1115cc0c4584SMatthew G. Knepley /*@C 1116cc0c4584SMatthew G. Knepley SNESMonitorFields - Monitors the residual for each field separately 1117cc0c4584SMatthew G. Knepley 1118cc0c4584SMatthew G. Knepley Collective on SNES 1119cc0c4584SMatthew G. Knepley 1120cc0c4584SMatthew G. Knepley Input Parameters: 1121cc0c4584SMatthew G. Knepley + snes - the SNES context 1122cc0c4584SMatthew G. Knepley . its - iteration number 1123cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual 1124d43b4f6eSBarry Smith - vf - PetscViewerAndFormat of type ASCII 1125cc0c4584SMatthew G. Knepley 1126cc0c4584SMatthew G. Knepley Notes: 1127cc0c4584SMatthew G. Knepley This routine prints the residual norm at each iteration. 1128cc0c4584SMatthew G. Knepley 1129cc0c4584SMatthew G. Knepley Level: intermediate 1130cc0c4584SMatthew G. Knepley 1131cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault() 1132cc0c4584SMatthew G. Knepley @*/ 1133d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 1134cc0c4584SMatthew G. Knepley { 1135d43b4f6eSBarry Smith PetscViewer viewer = vf->viewer; 1136cc0c4584SMatthew G. Knepley Vec res; 1137cc0c4584SMatthew G. Knepley DM dm; 1138cc0c4584SMatthew G. Knepley PetscSection s; 1139cc0c4584SMatthew G. Knepley const PetscScalar *r; 1140cc0c4584SMatthew G. Knepley PetscReal *lnorms, *norms; 1141cc0c4584SMatthew G. Knepley PetscInt numFields, f, pStart, pEnd, p; 1142cc0c4584SMatthew G. Knepley PetscErrorCode ierr; 1143cc0c4584SMatthew G. Knepley 1144cc0c4584SMatthew G. Knepley PetscFunctionBegin; 11454d4332d5SBarry Smith PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 11469e5d0892SLisandro Dalcin ierr = SNESGetFunction(snes, &res, NULL, NULL);CHKERRQ(ierr); 1147cc0c4584SMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 114892fd8e1eSJed Brown ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr); 1149cc0c4584SMatthew G. Knepley ierr = PetscSectionGetNumFields(s, &numFields);CHKERRQ(ierr); 1150cc0c4584SMatthew G. Knepley ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 1151cc0c4584SMatthew G. Knepley ierr = PetscCalloc2(numFields, &lnorms, numFields, &norms);CHKERRQ(ierr); 1152cc0c4584SMatthew G. Knepley ierr = VecGetArrayRead(res, &r);CHKERRQ(ierr); 1153cc0c4584SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1154cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 1155cc0c4584SMatthew G. Knepley PetscInt fdof, foff, d; 1156cc0c4584SMatthew G. Knepley 1157cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldDof(s, p, f, &fdof);CHKERRQ(ierr); 1158cc0c4584SMatthew G. Knepley ierr = PetscSectionGetFieldOffset(s, p, f, &foff);CHKERRQ(ierr); 1159cc0c4584SMatthew G. Knepley for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d])); 1160cc0c4584SMatthew G. Knepley } 1161cc0c4584SMatthew G. Knepley } 1162cc0c4584SMatthew G. Knepley ierr = VecRestoreArrayRead(res, &r);CHKERRQ(ierr); 1163820f2d46SBarry Smith ierr = MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 1164d43b4f6eSBarry Smith ierr = PetscViewerPushFormat(viewer,vf->format);CHKERRQ(ierr); 1165cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 1166cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm);CHKERRQ(ierr); 1167cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 1168cc0c4584SMatthew G. Knepley if (f > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 1169cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]));CHKERRQ(ierr); 1170cc0c4584SMatthew G. Knepley } 1171cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIIPrintf(viewer, "]\n");CHKERRQ(ierr); 1172cc0c4584SMatthew G. Knepley ierr = PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel);CHKERRQ(ierr); 1173d43b4f6eSBarry Smith ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 1174cc0c4584SMatthew G. Knepley ierr = PetscFree2(lnorms, norms);CHKERRQ(ierr); 1175cc0c4584SMatthew G. Knepley PetscFunctionReturn(0); 1176cc0c4584SMatthew G. Knepley } 117724cdb843SMatthew G. Knepley 117824cdb843SMatthew G. Knepley /********************* Residual Computation **************************/ 117924cdb843SMatthew G. Knepley 11806528b96dSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 11816528b96dSMatthew G. Knepley { 11826528b96dSMatthew G. Knepley PetscInt depth; 11836528b96dSMatthew G. Knepley PetscErrorCode ierr; 11846528b96dSMatthew G. Knepley 11856528b96dSMatthew G. Knepley PetscFunctionBegin; 11866528b96dSMatthew G. Knepley ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 11876528b96dSMatthew G. Knepley ierr = DMGetStratumIS(plex, "dim", depth, cellIS);CHKERRQ(ierr); 11886528b96dSMatthew G. Knepley if (!*cellIS) {ierr = DMGetStratumIS(plex, "depth", depth, cellIS);CHKERRQ(ierr);} 11896528b96dSMatthew G. Knepley PetscFunctionReturn(0); 11906528b96dSMatthew G. Knepley } 11916528b96dSMatthew G. Knepley 119224cdb843SMatthew G. Knepley /*@ 11938db23a53SJed Brown DMPlexSNESComputeResidualFEM - Sums the local residual into vector F from the local input X using pointwise functions specified by the user 119424cdb843SMatthew G. Knepley 119524cdb843SMatthew G. Knepley Input Parameters: 119624cdb843SMatthew G. Knepley + dm - The mesh 119724cdb843SMatthew G. Knepley . X - Local solution 119824cdb843SMatthew G. Knepley - user - The user context 119924cdb843SMatthew G. Knepley 120024cdb843SMatthew G. Knepley Output Parameter: 120124cdb843SMatthew G. Knepley . F - Local output vector 120224cdb843SMatthew G. Knepley 12038db23a53SJed Brown Notes: 12048db23a53SJed Brown The residual is summed into F; the caller is responsible for using VecZeroEntries() or otherwise ensuring that any data in F is intentional. 12058db23a53SJed Brown 120624cdb843SMatthew G. Knepley Level: developer 120724cdb843SMatthew G. Knepley 12087a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 120924cdb843SMatthew G. Knepley @*/ 121024cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 121124cdb843SMatthew G. Knepley { 12126da023fcSToby Isaac DM plex; 1213083401c6SMatthew G. Knepley IS allcellIS; 12146528b96dSMatthew G. Knepley PetscInt Nds, s; 121524cdb843SMatthew G. Knepley PetscErrorCode ierr; 121624cdb843SMatthew G. Knepley 121724cdb843SMatthew G. Knepley PetscFunctionBegin; 12186da023fcSToby Isaac ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 12196528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 12206528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 12216528b96dSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 12226528b96dSMatthew G. Knepley PetscDS ds; 12236528b96dSMatthew G. Knepley IS cellIS; 122406ad1575SMatthew G. Knepley PetscFormKey key; 12256528b96dSMatthew G. Knepley 12266528b96dSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr); 12276528b96dSMatthew G. Knepley key.value = 0; 12286528b96dSMatthew G. Knepley key.field = 0; 122906ad1575SMatthew G. Knepley key.part = 0; 12306528b96dSMatthew G. Knepley if (!key.label) { 12316528b96dSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 12326528b96dSMatthew G. Knepley cellIS = allcellIS; 12336528b96dSMatthew G. Knepley } else { 12346528b96dSMatthew G. Knepley IS pointIS; 12356528b96dSMatthew G. Knepley 12366528b96dSMatthew G. Knepley key.value = 1; 12376528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr); 12386528b96dSMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 12396528b96dSMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 12406528b96dSMatthew G. Knepley } 12416528b96dSMatthew G. Knepley ierr = DMPlexComputeResidual_Internal(plex, key, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr); 12426528b96dSMatthew G. Knepley ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 12436528b96dSMatthew G. Knepley } 12446528b96dSMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 12456528b96dSMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 12466528b96dSMatthew G. Knepley PetscFunctionReturn(0); 12476528b96dSMatthew G. Knepley } 12486528b96dSMatthew G. Knepley 12496528b96dSMatthew G. Knepley PetscErrorCode DMSNESComputeResidual(DM dm, Vec X, Vec F, void *user) 12506528b96dSMatthew G. Knepley { 12516528b96dSMatthew G. Knepley DM plex; 12526528b96dSMatthew G. Knepley IS allcellIS; 12536528b96dSMatthew G. Knepley PetscInt Nds, s; 12546528b96dSMatthew G. Knepley PetscErrorCode ierr; 12556528b96dSMatthew G. Knepley 12566528b96dSMatthew G. Knepley PetscFunctionBegin; 12576528b96dSMatthew G. Knepley ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 12586528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 12596528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1260083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1261083401c6SMatthew G. Knepley PetscDS ds; 1262083401c6SMatthew G. Knepley DMLabel label; 1263083401c6SMatthew G. Knepley IS cellIS; 1264083401c6SMatthew G. Knepley 1265083401c6SMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr); 12666528b96dSMatthew G. Knepley { 126706ad1575SMatthew G. Knepley PetscWeakFormKind resmap[2] = {PETSC_WF_F0, PETSC_WF_F1}; 12686528b96dSMatthew G. Knepley PetscWeakForm wf; 12696528b96dSMatthew G. Knepley PetscInt Nm = 2, m, Nk = 0, k, kp, off = 0; 127006ad1575SMatthew G. Knepley PetscFormKey *reskeys; 12716528b96dSMatthew G. Knepley 12726528b96dSMatthew G. Knepley /* Get unique residual keys */ 12736528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 12746528b96dSMatthew G. Knepley PetscInt Nkm; 127506ad1575SMatthew G. Knepley ierr = PetscHMapFormGetSize(ds->wf->form[resmap[m]], &Nkm);CHKERRQ(ierr); 12766528b96dSMatthew G. Knepley Nk += Nkm; 12776528b96dSMatthew G. Knepley } 12786528b96dSMatthew G. Knepley ierr = PetscMalloc1(Nk, &reskeys);CHKERRQ(ierr); 12796528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 128006ad1575SMatthew G. Knepley ierr = PetscHMapFormGetKeys(ds->wf->form[resmap[m]], &off, reskeys);CHKERRQ(ierr); 12816528b96dSMatthew G. Knepley } 12829ace16cdSJacob Faibussowitsch PetscAssertFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk); 128306ad1575SMatthew G. Knepley ierr = PetscFormKeySort(Nk, reskeys);CHKERRQ(ierr); 12846528b96dSMatthew G. Knepley for (k = 0, kp = 1; kp < Nk; ++kp) { 12856528b96dSMatthew G. Knepley if ((reskeys[k].label != reskeys[kp].label) || (reskeys[k].value != reskeys[kp].value)) { 12866528b96dSMatthew G. Knepley ++k; 12876528b96dSMatthew G. Knepley if (kp != k) reskeys[k] = reskeys[kp]; 12886528b96dSMatthew G. Knepley } 12896528b96dSMatthew G. Knepley } 12906528b96dSMatthew G. Knepley Nk = k; 12916528b96dSMatthew G. Knepley 12926528b96dSMatthew G. Knepley ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 12936528b96dSMatthew G. Knepley for (k = 0; k < Nk; ++k) { 12946528b96dSMatthew G. Knepley DMLabel label = reskeys[k].label; 12956528b96dSMatthew G. Knepley PetscInt val = reskeys[k].value; 12966528b96dSMatthew G. Knepley 1297083401c6SMatthew G. Knepley if (!label) { 1298083401c6SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 1299083401c6SMatthew G. Knepley cellIS = allcellIS; 1300083401c6SMatthew G. Knepley } else { 1301083401c6SMatthew G. Knepley IS pointIS; 1302083401c6SMatthew G. Knepley 13036528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr); 1304083401c6SMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 1305083401c6SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 13064a3e9fdbSToby Isaac } 13076528b96dSMatthew G. Knepley ierr = DMPlexComputeResidual_Internal(plex, reskeys[k], cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user);CHKERRQ(ierr); 13084a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 1309083401c6SMatthew G. Knepley } 13106528b96dSMatthew G. Knepley ierr = PetscFree(reskeys);CHKERRQ(ierr); 13116528b96dSMatthew G. Knepley } 13126528b96dSMatthew G. Knepley } 1313083401c6SMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 13149a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 131524cdb843SMatthew G. Knepley PetscFunctionReturn(0); 131624cdb843SMatthew G. Knepley } 131724cdb843SMatthew G. Knepley 1318bdd6f66aSToby Isaac /*@ 1319bdd6f66aSToby Isaac DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X 1320bdd6f66aSToby Isaac 1321bdd6f66aSToby Isaac Input Parameters: 1322bdd6f66aSToby Isaac + dm - The mesh 1323bdd6f66aSToby Isaac - user - The user context 1324bdd6f66aSToby Isaac 1325bdd6f66aSToby Isaac Output Parameter: 1326bdd6f66aSToby Isaac . X - Local solution 1327bdd6f66aSToby Isaac 1328bdd6f66aSToby Isaac Level: developer 1329bdd6f66aSToby Isaac 13307a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 1331bdd6f66aSToby Isaac @*/ 1332bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user) 1333bdd6f66aSToby Isaac { 1334bdd6f66aSToby Isaac DM plex; 1335bdd6f66aSToby Isaac PetscErrorCode ierr; 1336bdd6f66aSToby Isaac 1337bdd6f66aSToby Isaac PetscFunctionBegin; 1338bdd6f66aSToby Isaac ierr = DMSNESConvertPlex(dm,&plex,PETSC_TRUE);CHKERRQ(ierr); 1339bdd6f66aSToby Isaac ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL);CHKERRQ(ierr); 1340bdd6f66aSToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 1341bdd6f66aSToby Isaac PetscFunctionReturn(0); 1342bdd6f66aSToby Isaac } 1343bdd6f66aSToby Isaac 13447a73cf09SMatthew G. Knepley /*@ 13458e3a2eefSMatthew G. Knepley DMSNESComputeJacobianAction - Compute the action of the Jacobian J(X) on Y 13467a73cf09SMatthew G. Knepley 13477a73cf09SMatthew G. Knepley Input Parameters: 13488e3a2eefSMatthew G. Knepley + dm - The DM 13497a73cf09SMatthew G. Knepley . X - Local solution vector 13507a73cf09SMatthew G. Knepley . Y - Local input vector 13517a73cf09SMatthew G. Knepley - user - The user context 13527a73cf09SMatthew G. Knepley 13537a73cf09SMatthew G. Knepley Output Parameter: 13548e3a2eefSMatthew G. Knepley . F - lcoal output vector 13557a73cf09SMatthew G. Knepley 13567a73cf09SMatthew G. Knepley Level: developer 13577a73cf09SMatthew G. Knepley 13588e3a2eefSMatthew G. Knepley Notes: 13598e3a2eefSMatthew G. Knepley Users will typically use DMSNESCreateJacobianMF() followed by MatMult() instead of calling this routine directly. 13608e3a2eefSMatthew G. Knepley 1361a509fe9cSSatish Balay .seealso: DMSNESCreateJacobianMF(), DMPlexSNESComputeResidualFEM() 13627a73cf09SMatthew G. Knepley @*/ 13638e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESComputeJacobianAction(DM dm, Vec X, Vec Y, Vec F, void *user) 1364a925c78cSMatthew G. Knepley { 13658e3a2eefSMatthew G. Knepley DM plex; 13668e3a2eefSMatthew G. Knepley IS allcellIS; 13678e3a2eefSMatthew G. Knepley PetscInt Nds, s; 1368a925c78cSMatthew G. Knepley PetscErrorCode ierr; 1369a925c78cSMatthew G. Knepley 1370a925c78cSMatthew G. Knepley PetscFunctionBegin; 13717a73cf09SMatthew G. Knepley ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 13728e3a2eefSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 13738e3a2eefSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 13748e3a2eefSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 13758e3a2eefSMatthew G. Knepley PetscDS ds; 13768e3a2eefSMatthew G. Knepley DMLabel label; 13778e3a2eefSMatthew G. Knepley IS cellIS; 13787a73cf09SMatthew G. Knepley 13798e3a2eefSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, NULL, &ds);CHKERRQ(ierr); 13808e3a2eefSMatthew G. Knepley { 138106ad1575SMatthew G. Knepley PetscWeakFormKind jacmap[4] = {PETSC_WF_G0, PETSC_WF_G1, PETSC_WF_G2, PETSC_WF_G3}; 13828e3a2eefSMatthew G. Knepley PetscWeakForm wf; 13838e3a2eefSMatthew G. Knepley PetscInt Nm = 4, m, Nk = 0, k, kp, off = 0; 138406ad1575SMatthew G. Knepley PetscFormKey *jackeys; 13858e3a2eefSMatthew G. Knepley 13868e3a2eefSMatthew G. Knepley /* Get unique Jacobian keys */ 13878e3a2eefSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 13888e3a2eefSMatthew G. Knepley PetscInt Nkm; 138906ad1575SMatthew G. Knepley ierr = PetscHMapFormGetSize(ds->wf->form[jacmap[m]], &Nkm);CHKERRQ(ierr); 13908e3a2eefSMatthew G. Knepley Nk += Nkm; 13918e3a2eefSMatthew G. Knepley } 13928e3a2eefSMatthew G. Knepley ierr = PetscMalloc1(Nk, &jackeys);CHKERRQ(ierr); 13938e3a2eefSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 139406ad1575SMatthew G. Knepley ierr = PetscHMapFormGetKeys(ds->wf->form[jacmap[m]], &off, jackeys);CHKERRQ(ierr); 13958e3a2eefSMatthew G. Knepley } 13969ace16cdSJacob Faibussowitsch PetscAssertFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk); 139706ad1575SMatthew G. Knepley ierr = PetscFormKeySort(Nk, jackeys);CHKERRQ(ierr); 13988e3a2eefSMatthew G. Knepley for (k = 0, kp = 1; kp < Nk; ++kp) { 13998e3a2eefSMatthew G. Knepley if ((jackeys[k].label != jackeys[kp].label) || (jackeys[k].value != jackeys[kp].value)) { 14008e3a2eefSMatthew G. Knepley ++k; 14018e3a2eefSMatthew G. Knepley if (kp != k) jackeys[k] = jackeys[kp]; 14028e3a2eefSMatthew G. Knepley } 14038e3a2eefSMatthew G. Knepley } 14048e3a2eefSMatthew G. Knepley Nk = k; 14058e3a2eefSMatthew G. Knepley 14068e3a2eefSMatthew G. Knepley ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr); 14078e3a2eefSMatthew G. Knepley for (k = 0; k < Nk; ++k) { 14088e3a2eefSMatthew G. Knepley DMLabel label = jackeys[k].label; 14098e3a2eefSMatthew G. Knepley PetscInt val = jackeys[k].value; 14108e3a2eefSMatthew G. Knepley 14118e3a2eefSMatthew G. Knepley if (!label) { 14128e3a2eefSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 14138e3a2eefSMatthew G. Knepley cellIS = allcellIS; 14147a73cf09SMatthew G. Knepley } else { 14158e3a2eefSMatthew G. Knepley IS pointIS; 1416a925c78cSMatthew G. Knepley 14178e3a2eefSMatthew G. Knepley ierr = DMLabelGetStratumIS(label, val, &pointIS);CHKERRQ(ierr); 14188e3a2eefSMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 14198e3a2eefSMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1420a925c78cSMatthew G. Knepley } 14218e3a2eefSMatthew G. Knepley ierr = DMPlexComputeJacobian_Action_Internal(plex, jackeys[k], cellIS, 0.0, 0.0, X, NULL, Y, F, user);CHKERRQ(ierr); 14227a73cf09SMatthew G. Knepley ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 14238e3a2eefSMatthew G. Knepley } 14248e3a2eefSMatthew G. Knepley ierr = PetscFree(jackeys);CHKERRQ(ierr); 14258e3a2eefSMatthew G. Knepley } 14268e3a2eefSMatthew G. Knepley } 14278e3a2eefSMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 14287a73cf09SMatthew G. Knepley ierr = DMDestroy(&plex);CHKERRQ(ierr); 1429a925c78cSMatthew G. Knepley PetscFunctionReturn(0); 1430a925c78cSMatthew G. Knepley } 1431a925c78cSMatthew G. Knepley 143224cdb843SMatthew G. Knepley /*@ 143324cdb843SMatthew G. Knepley DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 143424cdb843SMatthew G. Knepley 143524cdb843SMatthew G. Knepley Input Parameters: 143624cdb843SMatthew G. Knepley + dm - The mesh 143724cdb843SMatthew G. Knepley . X - Local input vector 143824cdb843SMatthew G. Knepley - user - The user context 143924cdb843SMatthew G. Knepley 144024cdb843SMatthew G. Knepley Output Parameter: 144124cdb843SMatthew G. Knepley . Jac - Jacobian matrix 144224cdb843SMatthew G. Knepley 144324cdb843SMatthew G. Knepley Note: 144424cdb843SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 144524cdb843SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 144624cdb843SMatthew G. Knepley 144724cdb843SMatthew G. Knepley Level: developer 144824cdb843SMatthew G. Knepley 144924cdb843SMatthew G. Knepley .seealso: FormFunctionLocal() 145024cdb843SMatthew G. Knepley @*/ 145124cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user) 145224cdb843SMatthew G. Knepley { 14536da023fcSToby Isaac DM plex; 1454083401c6SMatthew G. Knepley IS allcellIS; 1455f04eb4edSMatthew G. Knepley PetscBool hasJac, hasPrec; 14566528b96dSMatthew G. Knepley PetscInt Nds, s; 145724cdb843SMatthew G. Knepley PetscErrorCode ierr; 145824cdb843SMatthew G. Knepley 145924cdb843SMatthew G. Knepley PetscFunctionBegin; 14606da023fcSToby Isaac ierr = DMSNESConvertPlex(dm, &plex, PETSC_TRUE);CHKERRQ(ierr); 14616528b96dSMatthew G. Knepley ierr = DMPlexGetAllCells_Internal(plex, &allcellIS);CHKERRQ(ierr); 14626528b96dSMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1463083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1464083401c6SMatthew G. Knepley PetscDS ds; 1465083401c6SMatthew G. Knepley IS cellIS; 146606ad1575SMatthew G. Knepley PetscFormKey key; 1467083401c6SMatthew G. Knepley 14686528b96dSMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &key.label, NULL, &ds);CHKERRQ(ierr); 14696528b96dSMatthew G. Knepley key.value = 0; 14706528b96dSMatthew G. Knepley key.field = 0; 147106ad1575SMatthew G. Knepley key.part = 0; 14726528b96dSMatthew G. Knepley if (!key.label) { 1473083401c6SMatthew G. Knepley ierr = PetscObjectReference((PetscObject) allcellIS);CHKERRQ(ierr); 1474083401c6SMatthew G. Knepley cellIS = allcellIS; 1475083401c6SMatthew G. Knepley } else { 1476083401c6SMatthew G. Knepley IS pointIS; 1477083401c6SMatthew G. Knepley 14786528b96dSMatthew G. Knepley key.value = 1; 14796528b96dSMatthew G. Knepley ierr = DMLabelGetStratumIS(key.label, key.value, &pointIS);CHKERRQ(ierr); 1480083401c6SMatthew G. Knepley ierr = ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS);CHKERRQ(ierr); 1481083401c6SMatthew G. Knepley ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1482083401c6SMatthew G. Knepley } 1483083401c6SMatthew G. Knepley if (!s) { 1484083401c6SMatthew G. Knepley ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr); 1485083401c6SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr); 1486f04eb4edSMatthew G. Knepley if (hasJac && hasPrec) {ierr = MatZeroEntries(Jac);CHKERRQ(ierr);} 1487f04eb4edSMatthew G. Knepley ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 1488083401c6SMatthew G. Knepley } 14896528b96dSMatthew G. Knepley ierr = DMPlexComputeJacobian_Internal(plex, key, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user);CHKERRQ(ierr); 14904a3e9fdbSToby Isaac ierr = ISDestroy(&cellIS);CHKERRQ(ierr); 1491083401c6SMatthew G. Knepley } 1492083401c6SMatthew G. Knepley ierr = ISDestroy(&allcellIS);CHKERRQ(ierr); 14939a81d013SToby Isaac ierr = DMDestroy(&plex);CHKERRQ(ierr); 149424cdb843SMatthew G. Knepley PetscFunctionReturn(0); 149524cdb843SMatthew G. Knepley } 14961878804aSMatthew G. Knepley 14978e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx 14988e3a2eefSMatthew G. Knepley { 14998e3a2eefSMatthew G. Knepley DM dm; 15008e3a2eefSMatthew G. Knepley Vec X; 15018e3a2eefSMatthew G. Knepley void *ctx; 15028e3a2eefSMatthew G. Knepley }; 15038e3a2eefSMatthew G. Knepley 15048e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Destroy_Private(Mat A) 15058e3a2eefSMatthew G. Knepley { 15068e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15078e3a2eefSMatthew G. Knepley PetscErrorCode ierr; 15088e3a2eefSMatthew G. Knepley 15098e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15103ec1f749SStefano Zampini ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr); 15118e3a2eefSMatthew G. Knepley ierr = MatShellSetContext(A, NULL);CHKERRQ(ierr); 15128e3a2eefSMatthew G. Knepley ierr = DMDestroy(&ctx->dm);CHKERRQ(ierr); 15138e3a2eefSMatthew G. Knepley ierr = VecDestroy(&ctx->X);CHKERRQ(ierr); 15148e3a2eefSMatthew G. Knepley ierr = PetscFree(ctx);CHKERRQ(ierr); 15158e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15168e3a2eefSMatthew G. Knepley } 15178e3a2eefSMatthew G. Knepley 15188e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Mult_Private(Mat A, Vec Y, Vec Z) 15198e3a2eefSMatthew G. Knepley { 15208e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15218e3a2eefSMatthew G. Knepley PetscErrorCode ierr; 15228e3a2eefSMatthew G. Knepley 15238e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15243ec1f749SStefano Zampini ierr = MatShellGetContext(A, &ctx);CHKERRQ(ierr); 15258e3a2eefSMatthew G. Knepley ierr = DMSNESComputeJacobianAction(ctx->dm, ctx->X, Y, Z, ctx->ctx);CHKERRQ(ierr); 15268e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15278e3a2eefSMatthew G. Knepley } 15288e3a2eefSMatthew G. Knepley 15298e3a2eefSMatthew G. Knepley /*@ 15308e3a2eefSMatthew G. Knepley DMSNESCreateJacobianMF - Create a Mat which computes the action of the Jacobian matrix-free 15318e3a2eefSMatthew G. Knepley 15328e3a2eefSMatthew G. Knepley Collective on dm 15338e3a2eefSMatthew G. Knepley 15348e3a2eefSMatthew G. Knepley Input Parameters: 15358e3a2eefSMatthew G. Knepley + dm - The DM 15368e3a2eefSMatthew G. Knepley . X - The evaluation point for the Jacobian 15378e3a2eefSMatthew G. Knepley - user - A user context, or NULL 15388e3a2eefSMatthew G. Knepley 15398e3a2eefSMatthew G. Knepley Output Parameter: 15408e3a2eefSMatthew G. Knepley . J - The Mat 15418e3a2eefSMatthew G. Knepley 15428e3a2eefSMatthew G. Knepley Level: advanced 15438e3a2eefSMatthew G. Knepley 15448e3a2eefSMatthew G. Knepley Notes: 15458e3a2eefSMatthew G. Knepley Vec X is kept in Mat J, so updating X then updates the evaluation point. 15468e3a2eefSMatthew G. Knepley 15478e3a2eefSMatthew G. Knepley .seealso: DMSNESComputeJacobianAction() 15488e3a2eefSMatthew G. Knepley @*/ 15498e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESCreateJacobianMF(DM dm, Vec X, void *user, Mat *J) 15508e3a2eefSMatthew G. Knepley { 15518e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15528e3a2eefSMatthew G. Knepley PetscInt n, N; 15538e3a2eefSMatthew G. Knepley PetscErrorCode ierr; 15548e3a2eefSMatthew G. Knepley 15558e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15568e3a2eefSMatthew G. Knepley ierr = MatCreate(PetscObjectComm((PetscObject) dm), J);CHKERRQ(ierr); 15578e3a2eefSMatthew G. Knepley ierr = MatSetType(*J, MATSHELL);CHKERRQ(ierr); 15588e3a2eefSMatthew G. Knepley ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr); 15598e3a2eefSMatthew G. Knepley ierr = VecGetSize(X, &N);CHKERRQ(ierr); 15608e3a2eefSMatthew G. Knepley ierr = MatSetSizes(*J, n, n, N, N);CHKERRQ(ierr); 15618e3a2eefSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 15628e3a2eefSMatthew G. Knepley ierr = PetscObjectReference((PetscObject) X);CHKERRQ(ierr); 15638e3a2eefSMatthew G. Knepley ierr = PetscMalloc1(1, &ctx);CHKERRQ(ierr); 15648e3a2eefSMatthew G. Knepley ctx->dm = dm; 15658e3a2eefSMatthew G. Knepley ctx->X = X; 15668e3a2eefSMatthew G. Knepley ctx->ctx = user; 15678e3a2eefSMatthew G. Knepley ierr = MatShellSetContext(*J, ctx);CHKERRQ(ierr); 15688e3a2eefSMatthew G. Knepley ierr = MatShellSetOperation(*J, MATOP_DESTROY, (void (*)(void)) DMSNESJacobianMF_Destroy_Private);CHKERRQ(ierr); 15698e3a2eefSMatthew G. Knepley ierr = MatShellSetOperation(*J, MATOP_MULT, (void (*)(void)) DMSNESJacobianMF_Mult_Private);CHKERRQ(ierr); 15708e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15718e3a2eefSMatthew G. Knepley } 15728e3a2eefSMatthew G. Knepley 157338cfc46eSPierre Jolivet /* 157438cfc46eSPierre Jolivet MatComputeNeumannOverlap - Computes an unassembled (Neumann) local overlapping Mat in nonlinear context. 157538cfc46eSPierre Jolivet 157638cfc46eSPierre Jolivet Input Parameters: 157738cfc46eSPierre Jolivet + X - SNES linearization point 157838cfc46eSPierre Jolivet . ovl - index set of overlapping subdomains 157938cfc46eSPierre Jolivet 158038cfc46eSPierre Jolivet Output Parameter: 158138cfc46eSPierre Jolivet . J - unassembled (Neumann) local matrix 158238cfc46eSPierre Jolivet 158338cfc46eSPierre Jolivet Level: intermediate 158438cfc46eSPierre Jolivet 158538cfc46eSPierre Jolivet .seealso: DMCreateNeumannOverlap(), MATIS, PCHPDDMSetAuxiliaryMat() 158638cfc46eSPierre Jolivet */ 158738cfc46eSPierre Jolivet static PetscErrorCode MatComputeNeumannOverlap_Plex(Mat J, PetscReal t, Vec X, Vec X_t, PetscReal s, IS ovl, void *ctx) 158838cfc46eSPierre Jolivet { 158938cfc46eSPierre Jolivet SNES snes; 159038cfc46eSPierre Jolivet Mat pJ; 159138cfc46eSPierre Jolivet DM ovldm,origdm; 159238cfc46eSPierre Jolivet DMSNES sdm; 159338cfc46eSPierre Jolivet PetscErrorCode (*bfun)(DM,Vec,void*); 159438cfc46eSPierre Jolivet PetscErrorCode (*jfun)(DM,Vec,Mat,Mat,void*); 159538cfc46eSPierre Jolivet void *bctx,*jctx; 159638cfc46eSPierre Jolivet PetscErrorCode ierr; 159738cfc46eSPierre Jolivet 159838cfc46eSPierre Jolivet PetscFunctionBegin; 159938cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_MATIS",(PetscObject*)&pJ);CHKERRQ(ierr); 16009ace16cdSJacob Faibussowitsch PetscAssertFalse(!pJ,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing overlapping Mat"); 160138cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Original_HPDDM",(PetscObject*)&origdm);CHKERRQ(ierr); 16029ace16cdSJacob Faibussowitsch PetscAssertFalse(!origdm,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing original DM"); 160338cfc46eSPierre Jolivet ierr = MatGetDM(pJ,&ovldm);CHKERRQ(ierr); 160438cfc46eSPierre Jolivet ierr = DMSNESGetBoundaryLocal(origdm,&bfun,&bctx);CHKERRQ(ierr); 160538cfc46eSPierre Jolivet ierr = DMSNESSetBoundaryLocal(ovldm,bfun,bctx);CHKERRQ(ierr); 160638cfc46eSPierre Jolivet ierr = DMSNESGetJacobianLocal(origdm,&jfun,&jctx);CHKERRQ(ierr); 160738cfc46eSPierre Jolivet ierr = DMSNESSetJacobianLocal(ovldm,jfun,jctx);CHKERRQ(ierr); 160838cfc46eSPierre Jolivet ierr = PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject*)&snes);CHKERRQ(ierr); 160938cfc46eSPierre Jolivet if (!snes) { 161038cfc46eSPierre Jolivet ierr = SNESCreate(PetscObjectComm((PetscObject)ovl),&snes);CHKERRQ(ierr); 161138cfc46eSPierre Jolivet ierr = SNESSetDM(snes,ovldm);CHKERRQ(ierr); 161238cfc46eSPierre Jolivet ierr = PetscObjectCompose((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject)snes);CHKERRQ(ierr); 161338cfc46eSPierre Jolivet ierr = PetscObjectDereference((PetscObject)snes);CHKERRQ(ierr); 161438cfc46eSPierre Jolivet } 161538cfc46eSPierre Jolivet ierr = DMGetDMSNES(ovldm,&sdm);CHKERRQ(ierr); 161638cfc46eSPierre Jolivet ierr = VecLockReadPush(X);CHKERRQ(ierr); 161738cfc46eSPierre Jolivet PetscStackPush("SNES user Jacobian function"); 161838cfc46eSPierre Jolivet ierr = (*sdm->ops->computejacobian)(snes,X,pJ,pJ,sdm->jacobianctx);CHKERRQ(ierr); 161938cfc46eSPierre Jolivet PetscStackPop; 162038cfc46eSPierre Jolivet ierr = VecLockReadPop(X);CHKERRQ(ierr); 162138cfc46eSPierre Jolivet /* this is a no-hop, just in case we decide to change the placeholder for the local Neumann matrix */ 162238cfc46eSPierre Jolivet { 162338cfc46eSPierre Jolivet Mat locpJ; 162438cfc46eSPierre Jolivet 162538cfc46eSPierre Jolivet ierr = MatISGetLocalMat(pJ,&locpJ);CHKERRQ(ierr); 162638cfc46eSPierre Jolivet ierr = MatCopy(locpJ,J,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 162738cfc46eSPierre Jolivet } 162838cfc46eSPierre Jolivet PetscFunctionReturn(0); 162938cfc46eSPierre Jolivet } 163038cfc46eSPierre Jolivet 1631a925c78cSMatthew G. Knepley /*@ 16329f520fc2SToby Isaac DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian. 16339f520fc2SToby Isaac 16349f520fc2SToby Isaac Input Parameters: 16359f520fc2SToby Isaac + dm - The DM object 1636dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary()) 16379f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual()) 16389f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian()) 16391a244344SSatish Balay 16401a244344SSatish Balay Level: developer 16419f520fc2SToby Isaac @*/ 16429f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx) 16439f520fc2SToby Isaac { 16449f520fc2SToby Isaac PetscErrorCode ierr; 16459f520fc2SToby Isaac 16469f520fc2SToby Isaac PetscFunctionBegin; 16479f520fc2SToby Isaac ierr = DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx);CHKERRQ(ierr); 16489f520fc2SToby Isaac ierr = DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx);CHKERRQ(ierr); 16499f520fc2SToby Isaac ierr = DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx);CHKERRQ(ierr); 165038cfc46eSPierre Jolivet ierr = PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",MatComputeNeumannOverlap_Plex);CHKERRQ(ierr); 16519f520fc2SToby Isaac PetscFunctionReturn(0); 16529f520fc2SToby Isaac } 16539f520fc2SToby Isaac 1654f017bcb6SMatthew G. Knepley /*@C 1655f017bcb6SMatthew G. Knepley DMSNESCheckDiscretization - Check the discretization error of the exact solution 1656f017bcb6SMatthew G. Knepley 1657f017bcb6SMatthew G. Knepley Input Parameters: 1658f017bcb6SMatthew G. Knepley + snes - the SNES object 1659f017bcb6SMatthew G. Knepley . dm - the DM 1660f2cacb80SMatthew G. Knepley . t - the time 1661f017bcb6SMatthew G. Knepley . u - a DM vector 1662f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1663f017bcb6SMatthew G. Knepley 1664f3c94560SMatthew G. Knepley Output Parameters: 1665f3c94560SMatthew G. Knepley . error - An array which holds the discretization error in each field, or NULL 1666f3c94560SMatthew G. Knepley 16677f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 16687f96f943SMatthew G. Knepley 1669f017bcb6SMatthew G. Knepley Level: developer 1670f017bcb6SMatthew G. Knepley 16717f96f943SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckResidual(), DMSNESCheckJacobian(), PetscDSSetExactSolution() 1672f017bcb6SMatthew G. Knepley @*/ 1673f2cacb80SMatthew G. Knepley PetscErrorCode DMSNESCheckDiscretization(SNES snes, DM dm, PetscReal t, Vec u, PetscReal tol, PetscReal error[]) 16741878804aSMatthew G. Knepley { 1675f017bcb6SMatthew G. Knepley PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 1676f017bcb6SMatthew G. Knepley void **ectxs; 1677f3c94560SMatthew G. Knepley PetscReal *err; 16787f96f943SMatthew G. Knepley MPI_Comm comm; 16797f96f943SMatthew G. Knepley PetscInt Nf, f; 16801878804aSMatthew G. Knepley PetscErrorCode ierr; 16811878804aSMatthew G. Knepley 16821878804aSMatthew G. Knepley PetscFunctionBegin; 1683f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1684f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1685064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(u, VEC_CLASSID, 4); 1686534a8f05SLisandro Dalcin if (error) PetscValidRealPointer(error, 6); 16877f96f943SMatthew G. Knepley 1688f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, t, u, NULL);CHKERRQ(ierr); 16897f96f943SMatthew G. Knepley ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr); 16907f96f943SMatthew G. Knepley 1691f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1692f017bcb6SMatthew G. Knepley ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 1693083401c6SMatthew G. Knepley ierr = PetscCalloc3(Nf, &exacts, Nf, &ectxs, PetscMax(1, Nf), &err);CHKERRQ(ierr); 16947f96f943SMatthew G. Knepley { 16957f96f943SMatthew G. Knepley PetscInt Nds, s; 16967f96f943SMatthew G. Knepley 1697083401c6SMatthew G. Knepley ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 1698083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 16997f96f943SMatthew G. Knepley PetscDS ds; 1700083401c6SMatthew G. Knepley DMLabel label; 1701083401c6SMatthew G. Knepley IS fieldIS; 17027f96f943SMatthew G. Knepley const PetscInt *fields; 17037f96f943SMatthew G. Knepley PetscInt dsNf, f; 1704083401c6SMatthew G. Knepley 1705083401c6SMatthew G. Knepley ierr = DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds);CHKERRQ(ierr); 1706083401c6SMatthew G. Knepley ierr = PetscDSGetNumFields(ds, &dsNf);CHKERRQ(ierr); 1707083401c6SMatthew G. Knepley ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 1708083401c6SMatthew G. Knepley for (f = 0; f < dsNf; ++f) { 1709083401c6SMatthew G. Knepley const PetscInt field = fields[f]; 1710083401c6SMatthew G. Knepley ierr = PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field]);CHKERRQ(ierr); 1711083401c6SMatthew G. Knepley } 1712083401c6SMatthew G. Knepley ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 1713083401c6SMatthew G. Knepley } 1714083401c6SMatthew G. Knepley } 1715f017bcb6SMatthew G. Knepley if (Nf > 1) { 1716f2cacb80SMatthew G. Knepley ierr = DMComputeL2FieldDiff(dm, t, exacts, ectxs, u, err);CHKERRQ(ierr); 1717f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 1718f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 17199ace16cdSJacob Faibussowitsch PetscAssertFalse(err[f] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g for field %D exceeds tolerance %g", (double) err[f], f, (double) tol); 17201878804aSMatthew G. Knepley } 1721b878532fSMatthew G. Knepley } else if (error) { 1722b878532fSMatthew G. Knepley for (f = 0; f < Nf; ++f) error[f] = err[f]; 17231878804aSMatthew G. Knepley } else { 1724f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Error: [");CHKERRQ(ierr); 1725f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 1726f017bcb6SMatthew G. Knepley if (f) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);} 1727f3c94560SMatthew G. Knepley ierr = PetscPrintf(comm, "%g", (double)err[f]);CHKERRQ(ierr); 17281878804aSMatthew G. Knepley } 1729f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "]\n");CHKERRQ(ierr); 1730f017bcb6SMatthew G. Knepley } 1731f017bcb6SMatthew G. Knepley } else { 1732f2cacb80SMatthew G. Knepley ierr = DMComputeL2Diff(dm, t, exacts, ectxs, u, &err[0]);CHKERRQ(ierr); 1733f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 17349ace16cdSJacob Faibussowitsch PetscAssertFalse(err[0] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g exceeds tolerance %g", (double) err[0], (double) tol); 1735b878532fSMatthew G. Knepley } else if (error) { 1736b878532fSMatthew G. Knepley error[0] = err[0]; 1737f017bcb6SMatthew G. Knepley } else { 1738f3c94560SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Error: %g\n", (double) err[0]);CHKERRQ(ierr); 1739f017bcb6SMatthew G. Knepley } 1740f017bcb6SMatthew G. Knepley } 1741f3c94560SMatthew G. Knepley ierr = PetscFree3(exacts, ectxs, err);CHKERRQ(ierr); 1742f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1743f017bcb6SMatthew G. Knepley } 1744f017bcb6SMatthew G. Knepley 1745f017bcb6SMatthew G. Knepley /*@C 1746f017bcb6SMatthew G. Knepley DMSNESCheckResidual - Check the residual of the exact solution 1747f017bcb6SMatthew G. Knepley 1748f017bcb6SMatthew G. Knepley Input Parameters: 1749f017bcb6SMatthew G. Knepley + snes - the SNES object 1750f017bcb6SMatthew G. Knepley . dm - the DM 1751f017bcb6SMatthew G. Knepley . u - a DM vector 1752f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1753f017bcb6SMatthew G. Knepley 1754f3c94560SMatthew G. Knepley Output Parameters: 1755f3c94560SMatthew G. Knepley . residual - The residual norm of the exact solution, or NULL 1756f3c94560SMatthew G. Knepley 1757f017bcb6SMatthew G. Knepley Level: developer 1758f017bcb6SMatthew G. Knepley 1759f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckJacobian() 1760f017bcb6SMatthew G. Knepley @*/ 1761f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckResidual(SNES snes, DM dm, Vec u, PetscReal tol, PetscReal *residual) 1762f017bcb6SMatthew G. Knepley { 1763f017bcb6SMatthew G. Knepley MPI_Comm comm; 1764f017bcb6SMatthew G. Knepley Vec r; 1765f017bcb6SMatthew G. Knepley PetscReal res; 1766f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1767f017bcb6SMatthew G. Knepley 1768f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1769f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1770f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1771f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1772534a8f05SLisandro Dalcin if (residual) PetscValidRealPointer(residual, 5); 1773f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1774f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr); 1775f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &r);CHKERRQ(ierr); 17761878804aSMatthew G. Knepley ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); 17771878804aSMatthew G. Knepley ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); 1778f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 17799ace16cdSJacob Faibussowitsch PetscAssertFalse(res > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Residual %g exceeds tolerance %g", (double) res, (double) tol); 1780b878532fSMatthew G. Knepley } else if (residual) { 1781b878532fSMatthew G. Knepley *residual = res; 1782f017bcb6SMatthew G. Knepley } else { 1783f017bcb6SMatthew G. Knepley ierr = PetscPrintf(comm, "L_2 Residual: %g\n", (double)res);CHKERRQ(ierr); 17841878804aSMatthew G. Knepley ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); 17851878804aSMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) r, "Initial Residual");CHKERRQ(ierr); 1786685405a1SBarry Smith ierr = PetscObjectSetOptionsPrefix((PetscObject)r,"res_");CHKERRQ(ierr); 1787685405a1SBarry Smith ierr = VecViewFromOptions(r, NULL, "-vec_view");CHKERRQ(ierr); 1788f017bcb6SMatthew G. Knepley } 1789f017bcb6SMatthew G. Knepley ierr = VecDestroy(&r);CHKERRQ(ierr); 1790f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1791f017bcb6SMatthew G. Knepley } 1792f017bcb6SMatthew G. Knepley 1793f017bcb6SMatthew G. Knepley /*@C 1794f3c94560SMatthew G. Knepley DMSNESCheckJacobian - Check the Jacobian of the exact solution against the residual using the Taylor Test 1795f017bcb6SMatthew G. Knepley 1796f017bcb6SMatthew G. Knepley Input Parameters: 1797f017bcb6SMatthew G. Knepley + snes - the SNES object 1798f017bcb6SMatthew G. Knepley . dm - the DM 1799f017bcb6SMatthew G. Knepley . u - a DM vector 1800f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1801f017bcb6SMatthew G. Knepley 1802f3c94560SMatthew G. Knepley Output Parameters: 1803f3c94560SMatthew G. Knepley + isLinear - Flag indicaing that the function looks linear, or NULL 1804f3c94560SMatthew G. Knepley - convRate - The rate of convergence of the linear model, or NULL 1805f3c94560SMatthew G. Knepley 1806f017bcb6SMatthew G. Knepley Level: developer 1807f017bcb6SMatthew G. Knepley 1808f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckResidual() 1809f017bcb6SMatthew G. Knepley @*/ 1810f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckJacobian(SNES snes, DM dm, Vec u, PetscReal tol, PetscBool *isLinear, PetscReal *convRate) 1811f017bcb6SMatthew G. Knepley { 1812f017bcb6SMatthew G. Knepley MPI_Comm comm; 1813f017bcb6SMatthew G. Knepley PetscDS ds; 1814f017bcb6SMatthew G. Knepley Mat J, M; 1815f017bcb6SMatthew G. Knepley MatNullSpace nullspace; 1816f3c94560SMatthew G. Knepley PetscReal slope, intercept; 18177f96f943SMatthew G. Knepley PetscBool hasJac, hasPrec, isLin = PETSC_FALSE; 1818f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1819f017bcb6SMatthew G. Knepley 1820f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1821f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1822f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1823f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1824534a8f05SLisandro Dalcin if (isLinear) PetscValidBoolPointer(isLinear, 5); 1825064a246eSJacob Faibussowitsch if (convRate) PetscValidRealPointer(convRate, 6); 1826f017bcb6SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) snes, &comm);CHKERRQ(ierr); 1827f2cacb80SMatthew G. Knepley ierr = DMComputeExactSolution(dm, 0.0, u, NULL);CHKERRQ(ierr); 1828f017bcb6SMatthew G. Knepley /* Create and view matrices */ 1829f017bcb6SMatthew G. Knepley ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr); 18307f96f943SMatthew G. Knepley ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 1831f017bcb6SMatthew G. Knepley ierr = PetscDSHasJacobian(ds, &hasJac);CHKERRQ(ierr); 1832f017bcb6SMatthew G. Knepley ierr = PetscDSHasJacobianPreconditioner(ds, &hasPrec);CHKERRQ(ierr); 1833282e7bb4SMatthew G. Knepley if (hasJac && hasPrec) { 1834282e7bb4SMatthew G. Knepley ierr = DMCreateMatrix(dm, &M);CHKERRQ(ierr); 1835282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, M);CHKERRQ(ierr); 1836f017bcb6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) M, "Preconditioning Matrix");CHKERRQ(ierr); 1837282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_");CHKERRQ(ierr); 1838282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(M, NULL, "-mat_view");CHKERRQ(ierr); 1839282e7bb4SMatthew G. Knepley ierr = MatDestroy(&M);CHKERRQ(ierr); 1840282e7bb4SMatthew G. Knepley } else { 1841282e7bb4SMatthew G. Knepley ierr = SNESComputeJacobian(snes, u, J, J);CHKERRQ(ierr); 1842282e7bb4SMatthew G. Knepley } 1843f017bcb6SMatthew G. Knepley ierr = PetscObjectSetName((PetscObject) J, "Jacobian");CHKERRQ(ierr); 1844282e7bb4SMatthew G. Knepley ierr = PetscObjectSetOptionsPrefix((PetscObject) J, "jac_");CHKERRQ(ierr); 1845282e7bb4SMatthew G. Knepley ierr = MatViewFromOptions(J, NULL, "-mat_view");CHKERRQ(ierr); 1846f017bcb6SMatthew G. Knepley /* Check nullspace */ 1847f017bcb6SMatthew G. Knepley ierr = MatGetNullSpace(J, &nullspace);CHKERRQ(ierr); 1848f017bcb6SMatthew G. Knepley if (nullspace) { 18491878804aSMatthew G. Knepley PetscBool isNull; 1850f017bcb6SMatthew G. Knepley ierr = MatNullSpaceTest(nullspace, J, &isNull);CHKERRQ(ierr); 18519ace16cdSJacob Faibussowitsch PetscAssertFalse(!isNull,comm, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid."); 18521878804aSMatthew G. Knepley } 1853f017bcb6SMatthew G. Knepley /* Taylor test */ 1854f017bcb6SMatthew G. Knepley { 1855f017bcb6SMatthew G. Knepley PetscRandom rand; 1856f017bcb6SMatthew G. Knepley Vec du, uhat, r, rhat, df; 1857f3c94560SMatthew G. Knepley PetscReal h; 1858f017bcb6SMatthew G. Knepley PetscReal *es, *hs, *errors; 1859f017bcb6SMatthew G. Knepley PetscReal hMax = 1.0, hMin = 1e-6, hMult = 0.1; 1860f017bcb6SMatthew G. Knepley PetscInt Nv, v; 1861f017bcb6SMatthew G. Knepley 1862f017bcb6SMatthew G. Knepley /* Choose a perturbation direction */ 1863f017bcb6SMatthew G. Knepley ierr = PetscRandomCreate(comm, &rand);CHKERRQ(ierr); 1864f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &du);CHKERRQ(ierr); 1865f017bcb6SMatthew G. Knepley ierr = VecSetRandom(du, rand);CHKERRQ(ierr); 1866f017bcb6SMatthew G. Knepley ierr = PetscRandomDestroy(&rand);CHKERRQ(ierr); 1867f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &df);CHKERRQ(ierr); 1868f017bcb6SMatthew G. Knepley ierr = MatMult(J, du, df);CHKERRQ(ierr); 1869f017bcb6SMatthew G. Knepley /* Evaluate residual at u, F(u), save in vector r */ 1870f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &r);CHKERRQ(ierr); 1871f017bcb6SMatthew G. Knepley ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); 1872f017bcb6SMatthew G. Knepley /* Look at the convergence of our Taylor approximation as we approach u */ 1873f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv); 1874f017bcb6SMatthew G. Knepley ierr = PetscCalloc3(Nv, &es, Nv, &hs, Nv, &errors);CHKERRQ(ierr); 1875f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &uhat);CHKERRQ(ierr); 1876f017bcb6SMatthew G. Knepley ierr = VecDuplicate(u, &rhat);CHKERRQ(ierr); 1877f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv) { 1878f017bcb6SMatthew G. Knepley ierr = VecWAXPY(uhat, h, du, u);CHKERRQ(ierr); 1879f017bcb6SMatthew G. Knepley /* F(\hat u) \approx F(u) + J(u) (uhat - u) = F(u) + h * J(u) du */ 1880f017bcb6SMatthew G. Knepley ierr = SNESComputeFunction(snes, uhat, rhat);CHKERRQ(ierr); 1881f017bcb6SMatthew G. Knepley ierr = VecAXPBYPCZ(rhat, -1.0, -h, 1.0, r, df);CHKERRQ(ierr); 1882f017bcb6SMatthew G. Knepley ierr = VecNorm(rhat, NORM_2, &errors[Nv]);CHKERRQ(ierr); 1883f017bcb6SMatthew G. Knepley 1884f017bcb6SMatthew G. Knepley es[Nv] = PetscLog10Real(errors[Nv]); 1885f017bcb6SMatthew G. Knepley hs[Nv] = PetscLog10Real(h); 1886f017bcb6SMatthew G. Knepley } 1887f017bcb6SMatthew G. Knepley ierr = VecDestroy(&uhat);CHKERRQ(ierr); 1888f017bcb6SMatthew G. Knepley ierr = VecDestroy(&rhat);CHKERRQ(ierr); 1889f017bcb6SMatthew G. Knepley ierr = VecDestroy(&df);CHKERRQ(ierr); 18901878804aSMatthew G. Knepley ierr = VecDestroy(&r);CHKERRQ(ierr); 1891f017bcb6SMatthew G. Knepley ierr = VecDestroy(&du);CHKERRQ(ierr); 1892f017bcb6SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1893f017bcb6SMatthew G. Knepley if ((tol >= 0) && (errors[v] > tol)) break; 1894f017bcb6SMatthew G. Knepley else if (errors[v] > PETSC_SMALL) break; 1895f017bcb6SMatthew G. Knepley } 1896f3c94560SMatthew G. Knepley if (v == Nv) isLin = PETSC_TRUE; 1897f017bcb6SMatthew G. Knepley ierr = PetscLinearRegression(Nv, hs, es, &slope, &intercept);CHKERRQ(ierr); 1898f017bcb6SMatthew G. Knepley ierr = PetscFree3(es, hs, errors);CHKERRQ(ierr); 1899f017bcb6SMatthew G. Knepley /* Slope should be about 2 */ 1900f017bcb6SMatthew G. Knepley if (tol >= 0) { 19019ace16cdSJacob Faibussowitsch PetscAssertFalse(!isLin && PetscAbsReal(2 - slope) > tol,comm, PETSC_ERR_ARG_WRONG, "Taylor approximation convergence rate should be 2, not %0.2f", (double) slope); 1902b878532fSMatthew G. Knepley } else if (isLinear || convRate) { 1903b878532fSMatthew G. Knepley if (isLinear) *isLinear = isLin; 1904b878532fSMatthew G. Knepley if (convRate) *convRate = slope; 1905f017bcb6SMatthew G. Knepley } else { 1906f3c94560SMatthew G. Knepley if (!isLin) {ierr = PetscPrintf(comm, "Taylor approximation converging at order %3.2f\n", (double) slope);CHKERRQ(ierr);} 1907f017bcb6SMatthew G. Knepley else {ierr = PetscPrintf(comm, "Function appears to be linear\n");CHKERRQ(ierr);} 1908f017bcb6SMatthew G. Knepley } 1909f017bcb6SMatthew G. Knepley } 19101878804aSMatthew G. Knepley ierr = MatDestroy(&J);CHKERRQ(ierr); 19111878804aSMatthew G. Knepley PetscFunctionReturn(0); 19121878804aSMatthew G. Knepley } 19131878804aSMatthew G. Knepley 19147f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheck_Internal(SNES snes, DM dm, Vec u) 1915f017bcb6SMatthew G. Knepley { 1916f017bcb6SMatthew G. Knepley PetscErrorCode ierr; 1917f017bcb6SMatthew G. Knepley 1918f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1919f2cacb80SMatthew G. Knepley ierr = DMSNESCheckDiscretization(snes, dm, 0.0, u, -1.0, NULL);CHKERRQ(ierr); 1920f3c94560SMatthew G. Knepley ierr = DMSNESCheckResidual(snes, dm, u, -1.0, NULL);CHKERRQ(ierr); 1921f3c94560SMatthew G. Knepley ierr = DMSNESCheckJacobian(snes, dm, u, -1.0, NULL, NULL);CHKERRQ(ierr); 1922f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1923f017bcb6SMatthew G. Knepley } 1924f017bcb6SMatthew G. Knepley 1925bee9a294SMatthew G. Knepley /*@C 1926bee9a294SMatthew G. Knepley DMSNESCheckFromOptions - Check the residual and Jacobian functions using the exact solution by outputting some diagnostic information 1927bee9a294SMatthew G. Knepley 1928bee9a294SMatthew G. Knepley Input Parameters: 1929bee9a294SMatthew G. Knepley + snes - the SNES object 19307f96f943SMatthew G. Knepley - u - representative SNES vector 19317f96f943SMatthew G. Knepley 19327f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 1933bee9a294SMatthew G. Knepley 1934bee9a294SMatthew G. Knepley Level: developer 1935bee9a294SMatthew G. Knepley @*/ 19367f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u) 19371878804aSMatthew G. Knepley { 19381878804aSMatthew G. Knepley DM dm; 19391878804aSMatthew G. Knepley Vec sol; 19401878804aSMatthew G. Knepley PetscBool check; 19411878804aSMatthew G. Knepley PetscErrorCode ierr; 19421878804aSMatthew G. Knepley 19431878804aSMatthew G. Knepley PetscFunctionBegin; 1944c5929fdfSBarry Smith ierr = PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check);CHKERRQ(ierr); 19451878804aSMatthew G. Knepley if (!check) PetscFunctionReturn(0); 19461878804aSMatthew G. Knepley ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 19471878804aSMatthew G. Knepley ierr = VecDuplicate(u, &sol);CHKERRQ(ierr); 19481878804aSMatthew G. Knepley ierr = SNESSetSolution(snes, sol);CHKERRQ(ierr); 19497f96f943SMatthew G. Knepley ierr = DMSNESCheck_Internal(snes, dm, sol);CHKERRQ(ierr); 19501878804aSMatthew G. Knepley ierr = VecDestroy(&sol);CHKERRQ(ierr); 1951552f7358SJed Brown PetscFunctionReturn(0); 1952552f7358SJed Brown } 1953