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 46649ef022SMatthew Knepley PetscFunctionBegin; 475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) snes, &comm)); 485f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes, &dm)); 49*28b400f6SJacob Faibussowitsch PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a SNES DM"); 50*28b400f6SJacob Faibussowitsch PetscCheck(nullspace,comm, PETSC_ERR_ARG_WRONG, "Cannot compute test without a Jacobian nullspace"); 515f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm, &ds)); 525f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetObjective(ds, pfield, pressure_Private)); 535f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceGetVecs(nullspace, NULL, &Nv, &nullvecs)); 542c71b3e2SJacob Faibussowitsch PetscCheckFalse(Nv != 1,comm, PETSC_ERR_ARG_OUTOFRANGE, "Can only handle a single null vector for pressure, not %D", Nv); 555f80ce2aSJacob Faibussowitsch CHKERRQ(VecDot(nullvecs[0], u, &pintd)); 562c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(pintd) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Discrete integral of pressure: %g", (double) PetscRealPart(pintd)); 575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds, &Nf)); 585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(Nf, &intc, Nf, &intn)); 595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeIntegralFEM(dm, nullvecs[0], intn, ctx)); 605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeIntegralFEM(dm, u, intc, ctx)); 615f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(u, -intc[pfield]/intn[pfield], nullvecs[0])); 62649ef022SMatthew Knepley #if defined (PETSC_USE_DEBUG) 635f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeIntegralFEM(dm, u, intc, ctx)); 642c71b3e2SJacob Faibussowitsch PetscCheckFalse(PetscAbsScalar(intc[pfield]) > PETSC_SMALL,comm, PETSC_ERR_ARG_WRONG, "Continuum integral of pressure after correction: %g", (double) PetscRealPart(intc[pfield])); 65649ef022SMatthew Knepley #endif 665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(intc, intn)); 67649ef022SMatthew Knepley PetscFunctionReturn(0); 68649ef022SMatthew Knepley } 69649ef022SMatthew Knepley 70649ef022SMatthew Knepley /*@C 71649ef022SMatthew 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(). 72649ef022SMatthew Knepley 73649ef022SMatthew Knepley Logically Collective on SNES 74649ef022SMatthew Knepley 75649ef022SMatthew Knepley Input Parameters: 76649ef022SMatthew Knepley + snes - the SNES context 77649ef022SMatthew Knepley . it - the iteration (0 indicates before any Newton steps) 78649ef022SMatthew Knepley . xnorm - 2-norm of current iterate 79649ef022SMatthew Knepley . snorm - 2-norm of current step 80649ef022SMatthew Knepley . fnorm - 2-norm of function at current iterate 81649ef022SMatthew Knepley - ctx - Optional user context 82649ef022SMatthew Knepley 83649ef022SMatthew Knepley Output Parameter: 84649ef022SMatthew Knepley . reason - SNES_CONVERGED_ITERATING, SNES_CONVERGED_ITS, or SNES_DIVERGED_FNORM_NAN 85649ef022SMatthew Knepley 86649ef022SMatthew Knepley Notes: 87649ef022SMatthew 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. 88649ef022SMatthew Knepley 89649ef022SMatthew Knepley Level: advanced 90649ef022SMatthew Knepley 91649ef022SMatthew Knepley .seealso: SNESConvergedDefault(), SNESSetConvergenceTest(), DMSetNullSpaceConstructor() 92649ef022SMatthew Knepley @*/ 93649ef022SMatthew Knepley PetscErrorCode SNESConvergedCorrectPressure(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *ctx) 94649ef022SMatthew Knepley { 95649ef022SMatthew Knepley PetscBool monitorIntegral = PETSC_FALSE; 96649ef022SMatthew Knepley 97649ef022SMatthew Knepley PetscFunctionBegin; 985f80ce2aSJacob Faibussowitsch CHKERRQ(SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx)); 99649ef022SMatthew Knepley if (monitorIntegral) { 100649ef022SMatthew Knepley Mat J; 101649ef022SMatthew Knepley Vec u; 102649ef022SMatthew Knepley MatNullSpace nullspace; 103649ef022SMatthew Knepley const Vec *nullvecs; 104649ef022SMatthew Knepley PetscScalar pintd; 105649ef022SMatthew Knepley 1065f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetSolution(snes, &u)); 1075f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetJacobian(snes, &J, NULL, NULL, NULL)); 1085f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNullSpace(J, &nullspace)); 1095f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceGetVecs(nullspace, NULL, NULL, &nullvecs)); 1105f80ce2aSJacob Faibussowitsch CHKERRQ(VecDot(nullvecs[0], u, &pintd)); 1115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(snes, "SNES: Discrete integral of pressure: %g\n", (double) PetscRealPart(pintd))); 112649ef022SMatthew Knepley } 113649ef022SMatthew Knepley if (*reason > 0) { 114649ef022SMatthew Knepley Mat J; 115649ef022SMatthew Knepley Vec u; 116649ef022SMatthew Knepley MatNullSpace nullspace; 117649ef022SMatthew Knepley PetscInt pfield = 1; 118649ef022SMatthew Knepley 1195f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetSolution(snes, &u)); 1205f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetJacobian(snes, &J, NULL, NULL, NULL)); 1215f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNullSpace(J, &nullspace)); 1225f80ce2aSJacob Faibussowitsch CHKERRQ(SNESCorrectDiscretePressure_Private(snes, pfield, nullspace, u, ctx)); 123649ef022SMatthew Knepley } 124649ef022SMatthew Knepley PetscFunctionReturn(0); 125649ef022SMatthew Knepley } 126649ef022SMatthew Knepley 12724cdb843SMatthew G. Knepley /************************** Interpolation *******************************/ 12824cdb843SMatthew G. Knepley 1296da023fcSToby Isaac static PetscErrorCode DMSNESConvertPlex(DM dm, DM *plex, PetscBool copy) 1306da023fcSToby Isaac { 1316da023fcSToby Isaac PetscBool isPlex; 1326da023fcSToby Isaac 1336da023fcSToby Isaac PetscFunctionBegin; 1345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex)); 1356da023fcSToby Isaac if (isPlex) { 1366da023fcSToby Isaac *plex = dm; 1375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm)); 138f7148743SMatthew G. Knepley } else { 1395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject) dm, "dm_plex", (PetscObject *) plex)); 140f7148743SMatthew G. Knepley if (!*plex) { 1415f80ce2aSJacob Faibussowitsch CHKERRQ(DMConvert(dm,DMPLEX,plex)); 1425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject) dm, "dm_plex", (PetscObject) *plex)); 1436da023fcSToby Isaac if (copy) { 1445f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDMSNES(dm, *plex)); 1455f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyAuxiliaryVec(dm, *plex)); 1466da023fcSToby Isaac } 147f7148743SMatthew G. Knepley } else { 1485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) *plex)); 149f7148743SMatthew G. Knepley } 1506da023fcSToby Isaac } 1516da023fcSToby Isaac PetscFunctionReturn(0); 1526da023fcSToby Isaac } 1536da023fcSToby Isaac 1544267b1a3SMatthew G. Knepley /*@C 1554267b1a3SMatthew G. Knepley DMInterpolationCreate - Creates a DMInterpolationInfo context 1564267b1a3SMatthew G. Knepley 157d083f849SBarry Smith Collective 1584267b1a3SMatthew G. Knepley 1594267b1a3SMatthew G. Knepley Input Parameter: 1604267b1a3SMatthew G. Knepley . comm - the communicator 1614267b1a3SMatthew G. Knepley 1624267b1a3SMatthew G. Knepley Output Parameter: 1634267b1a3SMatthew G. Knepley . ctx - the context 1644267b1a3SMatthew G. Knepley 1654267b1a3SMatthew G. Knepley Level: beginner 1664267b1a3SMatthew G. Knepley 1674267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationDestroy() 1684267b1a3SMatthew G. Knepley @*/ 1690adebc6cSBarry Smith PetscErrorCode DMInterpolationCreate(MPI_Comm comm, DMInterpolationInfo *ctx) 1700adebc6cSBarry Smith { 171552f7358SJed Brown PetscFunctionBegin; 172552f7358SJed Brown PetscValidPointer(ctx, 2); 1735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(ctx)); 1741aa26658SKarl Rupp 175552f7358SJed Brown (*ctx)->comm = comm; 176552f7358SJed Brown (*ctx)->dim = -1; 177552f7358SJed Brown (*ctx)->nInput = 0; 1780298fd71SBarry Smith (*ctx)->points = NULL; 1790298fd71SBarry Smith (*ctx)->cells = NULL; 180552f7358SJed Brown (*ctx)->n = -1; 1810298fd71SBarry Smith (*ctx)->coords = NULL; 182552f7358SJed Brown PetscFunctionReturn(0); 183552f7358SJed Brown } 184552f7358SJed Brown 1854267b1a3SMatthew G. Knepley /*@C 1864267b1a3SMatthew G. Knepley DMInterpolationSetDim - Sets the spatial dimension for the interpolation context 1874267b1a3SMatthew G. Knepley 1884267b1a3SMatthew G. Knepley Not collective 1894267b1a3SMatthew G. Knepley 1904267b1a3SMatthew G. Knepley Input Parameters: 1914267b1a3SMatthew G. Knepley + ctx - the context 1924267b1a3SMatthew G. Knepley - dim - the spatial dimension 1934267b1a3SMatthew G. Knepley 1944267b1a3SMatthew G. Knepley Level: intermediate 1954267b1a3SMatthew G. Knepley 1964267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 1974267b1a3SMatthew G. Knepley @*/ 1980adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDim(DMInterpolationInfo ctx, PetscInt dim) 1990adebc6cSBarry Smith { 200552f7358SJed Brown PetscFunctionBegin; 2012c71b3e2SJacob Faibussowitsch PetscCheckFalse((dim < 1) || (dim > 3),ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension for points: %D", dim); 202552f7358SJed Brown ctx->dim = dim; 203552f7358SJed Brown PetscFunctionReturn(0); 204552f7358SJed Brown } 205552f7358SJed Brown 2064267b1a3SMatthew G. Knepley /*@C 2074267b1a3SMatthew G. Knepley DMInterpolationGetDim - Gets the spatial dimension for the interpolation context 2084267b1a3SMatthew G. Knepley 2094267b1a3SMatthew G. Knepley Not collective 2104267b1a3SMatthew G. Knepley 2114267b1a3SMatthew G. Knepley Input Parameter: 2124267b1a3SMatthew G. Knepley . ctx - the context 2134267b1a3SMatthew G. Knepley 2144267b1a3SMatthew G. Knepley Output Parameter: 2154267b1a3SMatthew G. Knepley . dim - the spatial dimension 2164267b1a3SMatthew G. Knepley 2174267b1a3SMatthew G. Knepley Level: intermediate 2184267b1a3SMatthew G. Knepley 2194267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2204267b1a3SMatthew G. Knepley @*/ 2210adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDim(DMInterpolationInfo ctx, PetscInt *dim) 2220adebc6cSBarry Smith { 223552f7358SJed Brown PetscFunctionBegin; 224552f7358SJed Brown PetscValidIntPointer(dim, 2); 225552f7358SJed Brown *dim = ctx->dim; 226552f7358SJed Brown PetscFunctionReturn(0); 227552f7358SJed Brown } 228552f7358SJed Brown 2294267b1a3SMatthew G. Knepley /*@C 2304267b1a3SMatthew G. Knepley DMInterpolationSetDof - Sets the number of fields interpolated at a point for the interpolation context 2314267b1a3SMatthew G. Knepley 2324267b1a3SMatthew G. Knepley Not collective 2334267b1a3SMatthew G. Knepley 2344267b1a3SMatthew G. Knepley Input Parameters: 2354267b1a3SMatthew G. Knepley + ctx - the context 2364267b1a3SMatthew G. Knepley - dof - the number of fields 2374267b1a3SMatthew G. Knepley 2384267b1a3SMatthew G. Knepley Level: intermediate 2394267b1a3SMatthew G. Knepley 2404267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2414267b1a3SMatthew G. Knepley @*/ 2420adebc6cSBarry Smith PetscErrorCode DMInterpolationSetDof(DMInterpolationInfo ctx, PetscInt dof) 2430adebc6cSBarry Smith { 244552f7358SJed Brown PetscFunctionBegin; 2452c71b3e2SJacob Faibussowitsch PetscCheckFalse(dof < 1,ctx->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of components: %D", dof); 246552f7358SJed Brown ctx->dof = dof; 247552f7358SJed Brown PetscFunctionReturn(0); 248552f7358SJed Brown } 249552f7358SJed Brown 2504267b1a3SMatthew G. Knepley /*@C 2514267b1a3SMatthew G. Knepley DMInterpolationGetDof - Gets the number of fields interpolated at a point for the interpolation context 2524267b1a3SMatthew G. Knepley 2534267b1a3SMatthew G. Knepley Not collective 2544267b1a3SMatthew G. Knepley 2554267b1a3SMatthew G. Knepley Input Parameter: 2564267b1a3SMatthew G. Knepley . ctx - the context 2574267b1a3SMatthew G. Knepley 2584267b1a3SMatthew G. Knepley Output Parameter: 2594267b1a3SMatthew G. Knepley . dof - the number of fields 2604267b1a3SMatthew G. Knepley 2614267b1a3SMatthew G. Knepley Level: intermediate 2624267b1a3SMatthew G. Knepley 2634267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDof(), DMInterpolationEvaluate(), DMInterpolationAddPoints() 2644267b1a3SMatthew G. Knepley @*/ 2650adebc6cSBarry Smith PetscErrorCode DMInterpolationGetDof(DMInterpolationInfo ctx, PetscInt *dof) 2660adebc6cSBarry Smith { 267552f7358SJed Brown PetscFunctionBegin; 268552f7358SJed Brown PetscValidIntPointer(dof, 2); 269552f7358SJed Brown *dof = ctx->dof; 270552f7358SJed Brown PetscFunctionReturn(0); 271552f7358SJed Brown } 272552f7358SJed Brown 2734267b1a3SMatthew G. Knepley /*@C 2744267b1a3SMatthew G. Knepley DMInterpolationAddPoints - Add points at which we will interpolate the fields 2754267b1a3SMatthew G. Knepley 2764267b1a3SMatthew G. Knepley Not collective 2774267b1a3SMatthew G. Knepley 2784267b1a3SMatthew G. Knepley Input Parameters: 2794267b1a3SMatthew G. Knepley + ctx - the context 2804267b1a3SMatthew G. Knepley . n - the number of points 2814267b1a3SMatthew G. Knepley - points - the coordinates for each point, an array of size n * dim 2824267b1a3SMatthew G. Knepley 2834267b1a3SMatthew G. Knepley Note: The coordinate information is copied. 2844267b1a3SMatthew G. Knepley 2854267b1a3SMatthew G. Knepley Level: intermediate 2864267b1a3SMatthew G. Knepley 2874267b1a3SMatthew G. Knepley .seealso: DMInterpolationSetDim(), DMInterpolationEvaluate(), DMInterpolationCreate() 2884267b1a3SMatthew G. Knepley @*/ 2890adebc6cSBarry Smith PetscErrorCode DMInterpolationAddPoints(DMInterpolationInfo ctx, PetscInt n, PetscReal points[]) 2900adebc6cSBarry Smith { 291552f7358SJed Brown PetscFunctionBegin; 2922c71b3e2SJacob Faibussowitsch PetscCheckFalse(ctx->dim < 0,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 293*28b400f6SJacob Faibussowitsch PetscCheck(!ctx->points,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot add points multiple times yet"); 294552f7358SJed Brown ctx->nInput = n; 2951aa26658SKarl Rupp 2965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(n*ctx->dim, &ctx->points)); 2975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(ctx->points, points, n*ctx->dim)); 298552f7358SJed Brown PetscFunctionReturn(0); 299552f7358SJed Brown } 300552f7358SJed Brown 3014267b1a3SMatthew G. Knepley /*@C 30252aa1562SMatthew G. Knepley DMInterpolationSetUp - Compute spatial indices for point location during interpolation 3034267b1a3SMatthew G. Knepley 3044267b1a3SMatthew G. Knepley Collective on ctx 3054267b1a3SMatthew G. Knepley 3064267b1a3SMatthew G. Knepley Input Parameters: 3074267b1a3SMatthew G. Knepley + ctx - the context 3084267b1a3SMatthew G. Knepley . dm - the DM for the function space used for interpolation 30952aa1562SMatthew G. Knepley . redundantPoints - If PETSC_TRUE, all processes are passing in the same array of points. Otherwise, points need to be communicated among processes. 3107deeda50SSatish Balay - ignoreOutsideDomain - If PETSC_TRUE, ignore points outside the domain, otherwise return an error 3114267b1a3SMatthew G. Knepley 3124267b1a3SMatthew G. Knepley Level: intermediate 3134267b1a3SMatthew G. Knepley 3144267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 3154267b1a3SMatthew G. Knepley @*/ 31652aa1562SMatthew G. Knepley PetscErrorCode DMInterpolationSetUp(DMInterpolationInfo ctx, DM dm, PetscBool redundantPoints, PetscBool ignoreOutsideDomain) 3170adebc6cSBarry Smith { 318552f7358SJed Brown MPI_Comm comm = ctx->comm; 319552f7358SJed Brown PetscScalar *a; 320552f7358SJed Brown PetscInt p, q, i; 321552f7358SJed Brown PetscMPIInt rank, size; 322552f7358SJed Brown Vec pointVec; 3233a93e3b7SToby Isaac PetscSF cellSF; 324552f7358SJed Brown PetscLayout layout; 325552f7358SJed Brown PetscReal *globalPoints; 326cb313848SJed Brown PetscScalar *globalPointsScalar; 327552f7358SJed Brown const PetscInt *ranges; 328552f7358SJed Brown PetscMPIInt *counts, *displs; 3293a93e3b7SToby Isaac const PetscSFNode *foundCells; 3303a93e3b7SToby Isaac const PetscInt *foundPoints; 331552f7358SJed Brown PetscMPIInt *foundProcs, *globalProcs; 3323a93e3b7SToby Isaac PetscInt n, N, numFound; 333552f7358SJed Brown 33419436ca2SJed Brown PetscFunctionBegin; 335064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 3365f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 3375f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(comm, &rank)); 3382c71b3e2SJacob Faibussowitsch PetscCheckFalse(ctx->dim < 0,comm, PETSC_ERR_ARG_WRONGSTATE, "The spatial dimension has not been set"); 33919436ca2SJed Brown /* Locate points */ 34019436ca2SJed Brown n = ctx->nInput; 341552f7358SJed Brown if (!redundantPoints) { 3425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutCreate(comm, &layout)); 3435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetBlockSize(layout, 1)); 3445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetLocalSize(layout, n)); 3455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutSetUp(layout)); 3465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetSize(layout, &N)); 347552f7358SJed Brown /* Communicate all points to all processes */ 3485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(N*ctx->dim,&globalPoints,size,&counts,size,&displs)); 3495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutGetRanges(layout, &ranges)); 350552f7358SJed Brown for (p = 0; p < size; ++p) { 351552f7358SJed Brown counts[p] = (ranges[p+1] - ranges[p])*ctx->dim; 352552f7358SJed Brown displs[p] = ranges[p]*ctx->dim; 353552f7358SJed Brown } 3545f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Allgatherv(ctx->points, n*ctx->dim, MPIU_REAL, globalPoints, counts, displs, MPIU_REAL, comm)); 355552f7358SJed Brown } else { 356552f7358SJed Brown N = n; 357552f7358SJed Brown globalPoints = ctx->points; 35838ea73c8SJed Brown counts = displs = NULL; 35938ea73c8SJed Brown layout = NULL; 360552f7358SJed Brown } 361552f7358SJed Brown #if 0 3625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(N,&foundCells,N,&foundProcs,N,&globalProcs)); 36319436ca2SJed Brown /* foundCells[p] = m->locatePoint(&globalPoints[p*ctx->dim]); */ 364552f7358SJed Brown #else 365cb313848SJed Brown #if defined(PETSC_USE_COMPLEX) 3665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(N*ctx->dim,&globalPointsScalar)); 36746b3086cSToby Isaac for (i=0; i<N*ctx->dim; i++) globalPointsScalar[i] = globalPoints[i]; 368cb313848SJed Brown #else 369cb313848SJed Brown globalPointsScalar = globalPoints; 370cb313848SJed Brown #endif 3715f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeqWithArray(PETSC_COMM_SELF, ctx->dim, N*ctx->dim, globalPointsScalar, &pointVec)); 3725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(N,&foundProcs,N,&globalProcs)); 3737b5f2079SMatthew G. Knepley for (p = 0; p < N; ++p) {foundProcs[p] = size;} 3743a93e3b7SToby Isaac cellSF = NULL; 3755f80ce2aSJacob Faibussowitsch CHKERRQ(DMLocatePoints(dm, pointVec, DM_POINTLOCATION_REMOVE, &cellSF)); 3765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFGetGraph(cellSF,NULL,&numFound,&foundPoints,&foundCells)); 377552f7358SJed Brown #endif 3783a93e3b7SToby Isaac for (p = 0; p < numFound; ++p) { 3793a93e3b7SToby Isaac if (foundCells[p].index >= 0) foundProcs[foundPoints ? foundPoints[p] : p] = rank; 380552f7358SJed Brown } 381552f7358SJed Brown /* Let the lowest rank process own each point */ 3825f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(foundProcs, globalProcs, N, MPI_INT, MPI_MIN, comm)); 383552f7358SJed Brown ctx->n = 0; 384552f7358SJed Brown for (p = 0; p < N; ++p) { 38552aa1562SMatthew G. Knepley if (globalProcs[p] == size) { 386*28b400f6SJacob Faibussowitsch PetscCheck(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)); 387dd400576SPatrick Sanan else if (rank == 0) ++ctx->n; 38852aa1562SMatthew G. Knepley } else if (globalProcs[p] == rank) ++ctx->n; 389552f7358SJed Brown } 390552f7358SJed Brown /* Create coordinates vector and array of owned cells */ 3915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(ctx->n, &ctx->cells)); 3925f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(comm, &ctx->coords)); 3935f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(ctx->coords, ctx->n*ctx->dim, PETSC_DECIDE)); 3945f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(ctx->coords, ctx->dim)); 3955f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(ctx->coords,VECSTANDARD)); 3965f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(ctx->coords, &a)); 397552f7358SJed Brown for (p = 0, q = 0, i = 0; p < N; ++p) { 398552f7358SJed Brown if (globalProcs[p] == rank) { 399552f7358SJed Brown PetscInt d; 400552f7358SJed Brown 4011aa26658SKarl Rupp for (d = 0; d < ctx->dim; ++d, ++i) a[i] = globalPoints[p*ctx->dim+d]; 402f317b747SMatthew G. Knepley ctx->cells[q] = foundCells[q].index; 403f317b747SMatthew G. Knepley ++q; 404552f7358SJed Brown } 405dd400576SPatrick Sanan if (globalProcs[p] == size && rank == 0) { 40652aa1562SMatthew G. Knepley PetscInt d; 40752aa1562SMatthew G. Knepley 40852aa1562SMatthew G. Knepley for (d = 0; d < ctx->dim; ++d, ++i) a[i] = 0.; 40952aa1562SMatthew G. Knepley ctx->cells[q] = -1; 41052aa1562SMatthew G. Knepley ++q; 41152aa1562SMatthew G. Knepley } 412552f7358SJed Brown } 4135f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(ctx->coords, &a)); 414552f7358SJed Brown #if 0 4155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(foundCells,foundProcs,globalProcs)); 416552f7358SJed Brown #else 4175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(foundProcs,globalProcs)); 4185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSFDestroy(&cellSF)); 4195f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&pointVec)); 420552f7358SJed Brown #endif 4215f80ce2aSJacob Faibussowitsch if ((void*)globalPointsScalar != (void*)globalPoints) CHKERRQ(PetscFree(globalPointsScalar)); 4225f80ce2aSJacob Faibussowitsch if (!redundantPoints) CHKERRQ(PetscFree3(globalPoints,counts,displs)); 4235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLayoutDestroy(&layout)); 424552f7358SJed Brown PetscFunctionReturn(0); 425552f7358SJed Brown } 426552f7358SJed Brown 4274267b1a3SMatthew G. Knepley /*@C 4284267b1a3SMatthew G. Knepley DMInterpolationGetCoordinates - Gets a Vec with the coordinates of each interpolation point 4294267b1a3SMatthew G. Knepley 4304267b1a3SMatthew G. Knepley Collective on ctx 4314267b1a3SMatthew G. Knepley 4324267b1a3SMatthew G. Knepley Input Parameter: 4334267b1a3SMatthew G. Knepley . ctx - the context 4344267b1a3SMatthew G. Knepley 4354267b1a3SMatthew G. Knepley Output Parameter: 4364267b1a3SMatthew G. Knepley . coordinates - the coordinates of interpolation points 4374267b1a3SMatthew G. Knepley 4384267b1a3SMatthew 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. 4394267b1a3SMatthew G. Knepley 4404267b1a3SMatthew G. Knepley Level: intermediate 4414267b1a3SMatthew G. Knepley 4424267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 4434267b1a3SMatthew G. Knepley @*/ 4440adebc6cSBarry Smith PetscErrorCode DMInterpolationGetCoordinates(DMInterpolationInfo ctx, Vec *coordinates) 4450adebc6cSBarry Smith { 446552f7358SJed Brown PetscFunctionBegin; 447552f7358SJed Brown PetscValidPointer(coordinates, 2); 448*28b400f6SJacob Faibussowitsch PetscCheck(ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 449552f7358SJed Brown *coordinates = ctx->coords; 450552f7358SJed Brown PetscFunctionReturn(0); 451552f7358SJed Brown } 452552f7358SJed Brown 4534267b1a3SMatthew G. Knepley /*@C 4544267b1a3SMatthew G. Knepley DMInterpolationGetVector - Gets a Vec which can hold all the interpolated field values 4554267b1a3SMatthew G. Knepley 4564267b1a3SMatthew G. Knepley Collective on ctx 4574267b1a3SMatthew G. Knepley 4584267b1a3SMatthew G. Knepley Input Parameter: 4594267b1a3SMatthew G. Knepley . ctx - the context 4604267b1a3SMatthew G. Knepley 4614267b1a3SMatthew G. Knepley Output Parameter: 4624267b1a3SMatthew G. Knepley . v - a vector capable of holding the interpolated field values 4634267b1a3SMatthew G. Knepley 4644267b1a3SMatthew G. Knepley Note: This vector should be returned using DMInterpolationRestoreVector(). 4654267b1a3SMatthew G. Knepley 4664267b1a3SMatthew G. Knepley Level: intermediate 4674267b1a3SMatthew G. Knepley 4684267b1a3SMatthew G. Knepley .seealso: DMInterpolationRestoreVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 4694267b1a3SMatthew G. Knepley @*/ 4700adebc6cSBarry Smith PetscErrorCode DMInterpolationGetVector(DMInterpolationInfo ctx, Vec *v) 4710adebc6cSBarry Smith { 472552f7358SJed Brown PetscFunctionBegin; 473552f7358SJed Brown PetscValidPointer(v, 2); 474*28b400f6SJacob Faibussowitsch PetscCheck(ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 4755f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(ctx->comm, v)); 4765f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(*v, ctx->n*ctx->dof, PETSC_DECIDE)); 4775f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(*v, ctx->dof)); 4785f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(*v,VECSTANDARD)); 479552f7358SJed Brown PetscFunctionReturn(0); 480552f7358SJed Brown } 481552f7358SJed Brown 4824267b1a3SMatthew G. Knepley /*@C 4834267b1a3SMatthew G. Knepley DMInterpolationRestoreVector - Returns a Vec which can hold all the interpolated field values 4844267b1a3SMatthew G. Knepley 4854267b1a3SMatthew G. Knepley Collective on ctx 4864267b1a3SMatthew G. Knepley 4874267b1a3SMatthew G. Knepley Input Parameters: 4884267b1a3SMatthew G. Knepley + ctx - the context 4894267b1a3SMatthew G. Knepley - v - a vector capable of holding the interpolated field values 4904267b1a3SMatthew G. Knepley 4914267b1a3SMatthew G. Knepley Level: intermediate 4924267b1a3SMatthew G. Knepley 4934267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 4944267b1a3SMatthew G. Knepley @*/ 4950adebc6cSBarry Smith PetscErrorCode DMInterpolationRestoreVector(DMInterpolationInfo ctx, Vec *v) 4960adebc6cSBarry Smith { 497552f7358SJed Brown PetscFunctionBegin; 498552f7358SJed Brown PetscValidPointer(v, 2); 499*28b400f6SJacob Faibussowitsch PetscCheck(ctx->coords,ctx->comm, PETSC_ERR_ARG_WRONGSTATE, "The interpolation context has not been setup."); 5005f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(v)); 501552f7358SJed Brown PetscFunctionReturn(0); 502552f7358SJed Brown } 503552f7358SJed Brown 504cfe5744fSMatthew G. Knepley static inline PetscErrorCode DMInterpolate_Segment_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 505cfe5744fSMatthew G. Knepley { 506cfe5744fSMatthew G. Knepley PetscReal v0, J, invJ, detJ; 507cfe5744fSMatthew G. Knepley const PetscInt dof = ctx->dof; 508cfe5744fSMatthew G. Knepley const PetscScalar *coords; 509cfe5744fSMatthew G. Knepley PetscScalar *a; 510cfe5744fSMatthew G. Knepley PetscInt p; 511cfe5744fSMatthew G. Knepley 512cfe5744fSMatthew G. Knepley PetscFunctionBegin; 5135f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(ctx->coords, &coords)); 5145f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &a)); 515cfe5744fSMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 516cfe5744fSMatthew G. Knepley PetscInt c = ctx->cells[p]; 517cfe5744fSMatthew G. Knepley PetscScalar *x = NULL; 518cfe5744fSMatthew G. Knepley PetscReal xir[1]; 519cfe5744fSMatthew G. Knepley PetscInt xSize, comp; 520cfe5744fSMatthew G. Knepley 5215f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, &v0, &J, &invJ, &detJ)); 522cfe5744fSMatthew G. Knepley PetscCheck(detJ > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %" PetscInt_FMT, (double) detJ, c); 523cfe5744fSMatthew G. Knepley xir[0] = invJ*PetscRealPart(coords[p] - v0); 5245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x)); 525cfe5744fSMatthew G. Knepley if (2*dof == xSize) { 526cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp]*(1 - xir[0]) + x[1*dof+comp]*xir[0]; 527cfe5744fSMatthew G. Knepley } else if (dof == xSize) { 528cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp]; 529cfe5744fSMatthew G. Knepley } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input closure size %" PetscInt_FMT " must be either %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 2*dof, dof); 5305f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x)); 531cfe5744fSMatthew G. Knepley } 5325f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &a)); 5335f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(ctx->coords, &coords)); 534cfe5744fSMatthew G. Knepley PetscFunctionReturn(0); 535cfe5744fSMatthew G. Knepley } 536cfe5744fSMatthew G. Knepley 5379fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Triangle_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 538a6dfd86eSKarl Rupp { 539552f7358SJed Brown PetscReal *v0, *J, *invJ, detJ; 54056044e6dSMatthew G. Knepley const PetscScalar *coords; 54156044e6dSMatthew G. Knepley PetscScalar *a; 542552f7358SJed Brown PetscInt p; 543552f7358SJed Brown 544552f7358SJed Brown PetscFunctionBegin; 5455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ)); 5465f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(ctx->coords, &coords)); 5475f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &a)); 548552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 549552f7358SJed Brown PetscInt c = ctx->cells[p]; 550a1e44745SMatthew G. Knepley PetscScalar *x = NULL; 551552f7358SJed Brown PetscReal xi[4]; 552552f7358SJed Brown PetscInt d, f, comp; 553552f7358SJed Brown 5545f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); 5552c71b3e2SJacob Faibussowitsch PetscCheckFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 5565f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x)); 5571aa26658SKarl Rupp for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 5581aa26658SKarl Rupp 559552f7358SJed Brown for (d = 0; d < ctx->dim; ++d) { 560552f7358SJed Brown xi[d] = 0.0; 5611aa26658SKarl 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]); 5621aa26658SKarl 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]; 563552f7358SJed Brown } 5645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x)); 565552f7358SJed Brown } 5665f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &a)); 5675f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(ctx->coords, &coords)); 5685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(v0, J, invJ)); 569552f7358SJed Brown PetscFunctionReturn(0); 570552f7358SJed Brown } 571552f7358SJed Brown 5729fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Tetrahedron_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 5737a1931ceSMatthew G. Knepley { 5747a1931ceSMatthew G. Knepley PetscReal *v0, *J, *invJ, detJ; 57556044e6dSMatthew G. Knepley const PetscScalar *coords; 57656044e6dSMatthew G. Knepley PetscScalar *a; 5777a1931ceSMatthew G. Knepley PetscInt p; 5787a1931ceSMatthew G. Knepley 5797a1931ceSMatthew G. Knepley PetscFunctionBegin; 5805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(ctx->dim,&v0,ctx->dim*ctx->dim,&J,ctx->dim*ctx->dim,&invJ)); 5815f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(ctx->coords, &coords)); 5825f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &a)); 5837a1931ceSMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 5847a1931ceSMatthew G. Knepley PetscInt c = ctx->cells[p]; 5857a1931ceSMatthew G. Knepley const PetscInt order[3] = {2, 1, 3}; 5862584bbe8SMatthew G. Knepley PetscScalar *x = NULL; 5877a1931ceSMatthew G. Knepley PetscReal xi[4]; 5887a1931ceSMatthew G. Knepley PetscInt d, f, comp; 5897a1931ceSMatthew G. Knepley 5905f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ)); 5912c71b3e2SJacob Faibussowitsch PetscCheckFalse(detJ <= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %D", (double)detJ, c); 5925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, NULL, xLocal, c, NULL, &x)); 5937a1931ceSMatthew G. Knepley for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 5947a1931ceSMatthew G. Knepley 5957a1931ceSMatthew G. Knepley for (d = 0; d < ctx->dim; ++d) { 5967a1931ceSMatthew G. Knepley xi[d] = 0.0; 5977a1931ceSMatthew 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]); 5987a1931ceSMatthew 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]; 5997a1931ceSMatthew G. Knepley } 6005f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, NULL, &x)); 6017a1931ceSMatthew G. Knepley } 6025f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &a)); 6035f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(ctx->coords, &coords)); 6045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(v0, J, invJ)); 6057a1931ceSMatthew G. Knepley PetscFunctionReturn(0); 6067a1931ceSMatthew G. Knepley } 6077a1931ceSMatthew G. Knepley 6089fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 609552f7358SJed Brown { 610552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 611552f7358SJed Brown const PetscScalar x0 = vertices[0]; 612552f7358SJed Brown const PetscScalar y0 = vertices[1]; 613552f7358SJed Brown const PetscScalar x1 = vertices[2]; 614552f7358SJed Brown const PetscScalar y1 = vertices[3]; 615552f7358SJed Brown const PetscScalar x2 = vertices[4]; 616552f7358SJed Brown const PetscScalar y2 = vertices[5]; 617552f7358SJed Brown const PetscScalar x3 = vertices[6]; 618552f7358SJed Brown const PetscScalar y3 = vertices[7]; 619552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 620552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 621552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 622552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 623552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 624552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 62556044e6dSMatthew G. Knepley const PetscScalar *ref; 62656044e6dSMatthew G. Knepley PetscScalar *real; 627552f7358SJed Brown 628552f7358SJed Brown PetscFunctionBegin; 6295f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(Xref, &ref)); 6305f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(Xreal, &real)); 631552f7358SJed Brown { 632552f7358SJed Brown const PetscScalar p0 = ref[0]; 633552f7358SJed Brown const PetscScalar p1 = ref[1]; 634552f7358SJed Brown 635552f7358SJed Brown real[0] = x0 + f_1 * p0 + f_3 * p1 + f_01 * p0 * p1; 636552f7358SJed Brown real[1] = y0 + g_1 * p0 + g_3 * p1 + g_01 * p0 * p1; 637552f7358SJed Brown } 6385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops(28)); 6395f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(Xref, &ref)); 6405f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(Xreal, &real)); 641552f7358SJed Brown PetscFunctionReturn(0); 642552f7358SJed Brown } 643552f7358SJed Brown 644af0996ceSBarry Smith #include <petsc/private/dmimpl.h> 6459fbee547SJacob Faibussowitsch static inline PetscErrorCode QuadJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 646552f7358SJed Brown { 647552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 648552f7358SJed Brown const PetscScalar x0 = vertices[0]; 649552f7358SJed Brown const PetscScalar y0 = vertices[1]; 650552f7358SJed Brown const PetscScalar x1 = vertices[2]; 651552f7358SJed Brown const PetscScalar y1 = vertices[3]; 652552f7358SJed Brown const PetscScalar x2 = vertices[4]; 653552f7358SJed Brown const PetscScalar y2 = vertices[5]; 654552f7358SJed Brown const PetscScalar x3 = vertices[6]; 655552f7358SJed Brown const PetscScalar y3 = vertices[7]; 656552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 657552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 65856044e6dSMatthew G. Knepley const PetscScalar *ref; 659552f7358SJed Brown 660552f7358SJed Brown PetscFunctionBegin; 6615f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(Xref, &ref)); 662552f7358SJed Brown { 663552f7358SJed Brown const PetscScalar x = ref[0]; 664552f7358SJed Brown const PetscScalar y = ref[1]; 665552f7358SJed Brown const PetscInt rows[2] = {0, 1}; 666da80777bSKarl Rupp PetscScalar values[4]; 667da80777bSKarl Rupp 668da80777bSKarl Rupp values[0] = (x1 - x0 + f_01*y) * 0.5; values[1] = (x3 - x0 + f_01*x) * 0.5; 669da80777bSKarl Rupp values[2] = (y1 - y0 + g_01*y) * 0.5; values[3] = (y3 - y0 + g_01*x) * 0.5; 6705f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(J, 2, rows, 2, rows, values, INSERT_VALUES)); 671552f7358SJed Brown } 6725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops(30)); 6735f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(Xref, &ref)); 6745f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 6755f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 676552f7358SJed Brown PetscFunctionReturn(0); 677552f7358SJed Brown } 678552f7358SJed Brown 6799fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Quad_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 680a6dfd86eSKarl Rupp { 681fafc0619SMatthew G Knepley DM dmCoord; 682de73a395SMatthew G. Knepley PetscFE fem = NULL; 683552f7358SJed Brown SNES snes; 684552f7358SJed Brown KSP ksp; 685552f7358SJed Brown PC pc; 686552f7358SJed Brown Vec coordsLocal, r, ref, real; 687552f7358SJed Brown Mat J; 688716009bfSMatthew G. Knepley PetscTabulation T = NULL; 68956044e6dSMatthew G. Knepley const PetscScalar *coords; 69056044e6dSMatthew G. Knepley PetscScalar *a; 691716009bfSMatthew G. Knepley PetscReal xir[2] = {0., 0.}; 692de73a395SMatthew G. Knepley PetscInt Nf, p; 6935509d985SMatthew G. Knepley const PetscInt dof = ctx->dof; 694552f7358SJed Brown 695552f7358SJed Brown PetscFunctionBegin; 6965f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumFields(dm, &Nf)); 697716009bfSMatthew G. Knepley if (Nf) { 698cfe5744fSMatthew G. Knepley PetscObject obj; 699cfe5744fSMatthew G. Knepley PetscClassId id; 700cfe5744fSMatthew G. Knepley 7015f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetField(dm, 0, NULL, &obj)); 7025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj, &id)); 7035f80ce2aSJacob Faibussowitsch if (id == PETSCFE_CLASSID) {fem = (PetscFE) obj; CHKERRQ(PetscFECreateTabulation(fem, 1, 1, xir, 0, &T));} 704716009bfSMatthew G. Knepley } 7055f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordsLocal)); 7065f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &dmCoord)); 7075f80ce2aSJacob Faibussowitsch CHKERRQ(SNESCreate(PETSC_COMM_SELF, &snes)); 7085f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetOptionsPrefix(snes, "quad_interp_")); 7095f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &r)); 7105f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(r, 2, 2)); 7115f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(r,dm->vectype)); 7125f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(r, &ref)); 7135f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(r, &real)); 7145f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF, &J)); 7155f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(J, 2, 2, 2, 2)); 7165f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(J, MATSEQDENSE)); 7175f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(J)); 7185f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFunction(snes, r, QuadMap_Private, NULL)); 7195f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetJacobian(snes, J, J, QuadJacobian_Private, NULL)); 7205f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetKSP(snes, &ksp)); 7215f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(ksp, &pc)); 7225f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc, PCLU)); 7235f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFromOptions(snes)); 724552f7358SJed Brown 7255f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(ctx->coords, &coords)); 7265f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &a)); 727552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 728a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 729552f7358SJed Brown PetscScalar *xi; 730552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 731552f7358SJed Brown 732552f7358SJed Brown /* Can make this do all points at once */ 7335f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 7342c71b3e2SJacob Faibussowitsch PetscCheckFalse(4*2 != coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid closure size %D should be %d", coordSize, 4*2); 7355f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x)); 7365f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFunction(snes, NULL, NULL, vertices)); 7375f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetJacobian(snes, NULL, NULL, NULL, vertices)); 7385f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(real, &xi)); 739552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 740552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 7415f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(real, &xi)); 7425f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSolve(snes, real, ref)); 7435f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(ref, &xi)); 744cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 745cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 746cfe5744fSMatthew G. Knepley if (4*dof == xSize) { 747cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) 748cfe5744fSMatthew 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]; 749cfe5744fSMatthew G. Knepley } else if (dof == xSize) { 750cfe5744fSMatthew G. Knepley for (comp = 0; comp < dof; ++comp) a[p*dof+comp] = x[0*dof+comp]; 751cfe5744fSMatthew G. Knepley } else { 7525509d985SMatthew G. Knepley PetscInt d; 7531aa26658SKarl Rupp 7542c71b3e2SJacob Faibussowitsch PetscCheck(fem, ctx->comm, PETSC_ERR_ARG_WRONG, "Cannot have a higher order interpolant if the discretization is not PetscFE"); 7555509d985SMatthew G. Knepley xir[0] = 2.0*xir[0] - 1.0; xir[1] = 2.0*xir[1] - 1.0; 7565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEComputeTabulation(fem, 1, xir, 0, T)); 7575509d985SMatthew G. Knepley for (comp = 0; comp < dof; ++comp) { 7585509d985SMatthew G. Knepley a[p*dof+comp] = 0.0; 7595509d985SMatthew G. Knepley for (d = 0; d < xSize/dof; ++d) { 760ef0bb6c7SMatthew G. Knepley a[p*dof+comp] += x[d*dof+comp]*T->T[0][d*dof+comp]; 7615509d985SMatthew G. Knepley } 7625509d985SMatthew G. Knepley } 7635509d985SMatthew G. Knepley } 7645f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(ref, &xi)); 7655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 7665f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x)); 767552f7358SJed Brown } 7685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTabulationDestroy(&T)); 7695f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &a)); 7705f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(ctx->coords, &coords)); 771552f7358SJed Brown 7725f80ce2aSJacob Faibussowitsch CHKERRQ(SNESDestroy(&snes)); 7735f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&r)); 7745f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ref)); 7755f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&real)); 7765f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&J)); 777552f7358SJed Brown PetscFunctionReturn(0); 778552f7358SJed Brown } 779552f7358SJed Brown 7809fbee547SJacob Faibussowitsch static inline PetscErrorCode HexMap_Private(SNES snes, Vec Xref, Vec Xreal, void *ctx) 781552f7358SJed Brown { 782552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 783552f7358SJed Brown const PetscScalar x0 = vertices[0]; 784552f7358SJed Brown const PetscScalar y0 = vertices[1]; 785552f7358SJed Brown const PetscScalar z0 = vertices[2]; 7867a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 7877a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 7887a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 789552f7358SJed Brown const PetscScalar x2 = vertices[6]; 790552f7358SJed Brown const PetscScalar y2 = vertices[7]; 791552f7358SJed Brown const PetscScalar z2 = vertices[8]; 7927a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 7937a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 7947a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 795552f7358SJed Brown const PetscScalar x4 = vertices[12]; 796552f7358SJed Brown const PetscScalar y4 = vertices[13]; 797552f7358SJed Brown const PetscScalar z4 = vertices[14]; 798552f7358SJed Brown const PetscScalar x5 = vertices[15]; 799552f7358SJed Brown const PetscScalar y5 = vertices[16]; 800552f7358SJed Brown const PetscScalar z5 = vertices[17]; 801552f7358SJed Brown const PetscScalar x6 = vertices[18]; 802552f7358SJed Brown const PetscScalar y6 = vertices[19]; 803552f7358SJed Brown const PetscScalar z6 = vertices[20]; 804552f7358SJed Brown const PetscScalar x7 = vertices[21]; 805552f7358SJed Brown const PetscScalar y7 = vertices[22]; 806552f7358SJed Brown const PetscScalar z7 = vertices[23]; 807552f7358SJed Brown const PetscScalar f_1 = x1 - x0; 808552f7358SJed Brown const PetscScalar g_1 = y1 - y0; 809552f7358SJed Brown const PetscScalar h_1 = z1 - z0; 810552f7358SJed Brown const PetscScalar f_3 = x3 - x0; 811552f7358SJed Brown const PetscScalar g_3 = y3 - y0; 812552f7358SJed Brown const PetscScalar h_3 = z3 - z0; 813552f7358SJed Brown const PetscScalar f_4 = x4 - x0; 814552f7358SJed Brown const PetscScalar g_4 = y4 - y0; 815552f7358SJed Brown const PetscScalar h_4 = z4 - z0; 816552f7358SJed Brown const PetscScalar f_01 = x2 - x1 - x3 + x0; 817552f7358SJed Brown const PetscScalar g_01 = y2 - y1 - y3 + y0; 818552f7358SJed Brown const PetscScalar h_01 = z2 - z1 - z3 + z0; 819552f7358SJed Brown const PetscScalar f_12 = x7 - x3 - x4 + x0; 820552f7358SJed Brown const PetscScalar g_12 = y7 - y3 - y4 + y0; 821552f7358SJed Brown const PetscScalar h_12 = z7 - z3 - z4 + z0; 822552f7358SJed Brown const PetscScalar f_02 = x5 - x1 - x4 + x0; 823552f7358SJed Brown const PetscScalar g_02 = y5 - y1 - y4 + y0; 824552f7358SJed Brown const PetscScalar h_02 = z5 - z1 - z4 + z0; 825552f7358SJed Brown const PetscScalar f_012 = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 826552f7358SJed Brown const PetscScalar g_012 = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 827552f7358SJed Brown const PetscScalar h_012 = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 82856044e6dSMatthew G. Knepley const PetscScalar *ref; 82956044e6dSMatthew G. Knepley PetscScalar *real; 830552f7358SJed Brown 831552f7358SJed Brown PetscFunctionBegin; 8325f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(Xref, &ref)); 8335f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(Xreal, &real)); 834552f7358SJed Brown { 835552f7358SJed Brown const PetscScalar p0 = ref[0]; 836552f7358SJed Brown const PetscScalar p1 = ref[1]; 837552f7358SJed Brown const PetscScalar p2 = ref[2]; 838552f7358SJed Brown 839552f7358SJed 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; 840552f7358SJed 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; 841552f7358SJed 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; 842552f7358SJed Brown } 8435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops(114)); 8445f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(Xref, &ref)); 8455f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(Xreal, &real)); 846552f7358SJed Brown PetscFunctionReturn(0); 847552f7358SJed Brown } 848552f7358SJed Brown 8499fbee547SJacob Faibussowitsch static inline PetscErrorCode HexJacobian_Private(SNES snes, Vec Xref, Mat J, Mat M, void *ctx) 850552f7358SJed Brown { 851552f7358SJed Brown const PetscScalar *vertices = (const PetscScalar*) ctx; 852552f7358SJed Brown const PetscScalar x0 = vertices[0]; 853552f7358SJed Brown const PetscScalar y0 = vertices[1]; 854552f7358SJed Brown const PetscScalar z0 = vertices[2]; 8557a1931ceSMatthew G. Knepley const PetscScalar x1 = vertices[9]; 8567a1931ceSMatthew G. Knepley const PetscScalar y1 = vertices[10]; 8577a1931ceSMatthew G. Knepley const PetscScalar z1 = vertices[11]; 858552f7358SJed Brown const PetscScalar x2 = vertices[6]; 859552f7358SJed Brown const PetscScalar y2 = vertices[7]; 860552f7358SJed Brown const PetscScalar z2 = vertices[8]; 8617a1931ceSMatthew G. Knepley const PetscScalar x3 = vertices[3]; 8627a1931ceSMatthew G. Knepley const PetscScalar y3 = vertices[4]; 8637a1931ceSMatthew G. Knepley const PetscScalar z3 = vertices[5]; 864552f7358SJed Brown const PetscScalar x4 = vertices[12]; 865552f7358SJed Brown const PetscScalar y4 = vertices[13]; 866552f7358SJed Brown const PetscScalar z4 = vertices[14]; 867552f7358SJed Brown const PetscScalar x5 = vertices[15]; 868552f7358SJed Brown const PetscScalar y5 = vertices[16]; 869552f7358SJed Brown const PetscScalar z5 = vertices[17]; 870552f7358SJed Brown const PetscScalar x6 = vertices[18]; 871552f7358SJed Brown const PetscScalar y6 = vertices[19]; 872552f7358SJed Brown const PetscScalar z6 = vertices[20]; 873552f7358SJed Brown const PetscScalar x7 = vertices[21]; 874552f7358SJed Brown const PetscScalar y7 = vertices[22]; 875552f7358SJed Brown const PetscScalar z7 = vertices[23]; 876552f7358SJed Brown const PetscScalar f_xy = x2 - x1 - x3 + x0; 877552f7358SJed Brown const PetscScalar g_xy = y2 - y1 - y3 + y0; 878552f7358SJed Brown const PetscScalar h_xy = z2 - z1 - z3 + z0; 879552f7358SJed Brown const PetscScalar f_yz = x7 - x3 - x4 + x0; 880552f7358SJed Brown const PetscScalar g_yz = y7 - y3 - y4 + y0; 881552f7358SJed Brown const PetscScalar h_yz = z7 - z3 - z4 + z0; 882552f7358SJed Brown const PetscScalar f_xz = x5 - x1 - x4 + x0; 883552f7358SJed Brown const PetscScalar g_xz = y5 - y1 - y4 + y0; 884552f7358SJed Brown const PetscScalar h_xz = z5 - z1 - z4 + z0; 885552f7358SJed Brown const PetscScalar f_xyz = x6 - x0 + x1 - x2 + x3 + x4 - x5 - x7; 886552f7358SJed Brown const PetscScalar g_xyz = y6 - y0 + y1 - y2 + y3 + y4 - y5 - y7; 887552f7358SJed Brown const PetscScalar h_xyz = z6 - z0 + z1 - z2 + z3 + z4 - z5 - z7; 88856044e6dSMatthew G. Knepley const PetscScalar *ref; 889552f7358SJed Brown 890552f7358SJed Brown PetscFunctionBegin; 8915f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(Xref, &ref)); 892552f7358SJed Brown { 893552f7358SJed Brown const PetscScalar x = ref[0]; 894552f7358SJed Brown const PetscScalar y = ref[1]; 895552f7358SJed Brown const PetscScalar z = ref[2]; 896552f7358SJed Brown const PetscInt rows[3] = {0, 1, 2}; 897da80777bSKarl Rupp PetscScalar values[9]; 898da80777bSKarl Rupp 899da80777bSKarl Rupp values[0] = (x1 - x0 + f_xy*y + f_xz*z + f_xyz*y*z) / 2.0; 900da80777bSKarl Rupp values[1] = (x3 - x0 + f_xy*x + f_yz*z + f_xyz*x*z) / 2.0; 901da80777bSKarl Rupp values[2] = (x4 - x0 + f_yz*y + f_xz*x + f_xyz*x*y) / 2.0; 902da80777bSKarl Rupp values[3] = (y1 - y0 + g_xy*y + g_xz*z + g_xyz*y*z) / 2.0; 903da80777bSKarl Rupp values[4] = (y3 - y0 + g_xy*x + g_yz*z + g_xyz*x*z) / 2.0; 904da80777bSKarl Rupp values[5] = (y4 - y0 + g_yz*y + g_xz*x + g_xyz*x*y) / 2.0; 905da80777bSKarl Rupp values[6] = (z1 - z0 + h_xy*y + h_xz*z + h_xyz*y*z) / 2.0; 906da80777bSKarl Rupp values[7] = (z3 - z0 + h_xy*x + h_yz*z + h_xyz*x*z) / 2.0; 907da80777bSKarl Rupp values[8] = (z4 - z0 + h_yz*y + h_xz*x + h_xyz*x*y) / 2.0; 9081aa26658SKarl Rupp 9095f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(J, 3, rows, 3, rows, values, INSERT_VALUES)); 910552f7358SJed Brown } 9115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogFlops(152)); 9125f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(Xref, &ref)); 9135f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY)); 9145f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY)); 915552f7358SJed Brown PetscFunctionReturn(0); 916552f7358SJed Brown } 917552f7358SJed Brown 9189fbee547SJacob Faibussowitsch static inline PetscErrorCode DMInterpolate_Hex_Private(DMInterpolationInfo ctx, DM dm, Vec xLocal, Vec v) 919a6dfd86eSKarl Rupp { 920fafc0619SMatthew G Knepley DM dmCoord; 921552f7358SJed Brown SNES snes; 922552f7358SJed Brown KSP ksp; 923552f7358SJed Brown PC pc; 924552f7358SJed Brown Vec coordsLocal, r, ref, real; 925552f7358SJed Brown Mat J; 92656044e6dSMatthew G. Knepley const PetscScalar *coords; 92756044e6dSMatthew G. Knepley PetscScalar *a; 928552f7358SJed Brown PetscInt p; 929552f7358SJed Brown 930552f7358SJed Brown PetscFunctionBegin; 9315f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinatesLocal(dm, &coordsLocal)); 9325f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDM(dm, &dmCoord)); 9335f80ce2aSJacob Faibussowitsch CHKERRQ(SNESCreate(PETSC_COMM_SELF, &snes)); 9345f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetOptionsPrefix(snes, "hex_interp_")); 9355f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(PETSC_COMM_SELF, &r)); 9365f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetSizes(r, 3, 3)); 9375f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetType(r,dm->vectype)); 9385f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(r, &ref)); 9395f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(r, &real)); 9405f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PETSC_COMM_SELF, &J)); 9415f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(J, 3, 3, 3, 3)); 9425f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(J, MATSEQDENSE)); 9435f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(J)); 9445f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFunction(snes, r, HexMap_Private, NULL)); 9455f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetJacobian(snes, J, J, HexJacobian_Private, NULL)); 9465f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetKSP(snes, &ksp)); 9475f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(ksp, &pc)); 9485f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(pc, PCLU)); 9495f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFromOptions(snes)); 950552f7358SJed Brown 9515f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(ctx->coords, &coords)); 9525f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(v, &a)); 953552f7358SJed Brown for (p = 0; p < ctx->n; ++p) { 954a1e44745SMatthew G. Knepley PetscScalar *x = NULL, *vertices = NULL; 955552f7358SJed Brown PetscScalar *xi; 956cb313848SJed Brown PetscReal xir[3]; 957552f7358SJed Brown PetscInt c = ctx->cells[p], comp, coordSize, xSize; 958552f7358SJed Brown 959552f7358SJed Brown /* Can make this do all points at once */ 9605f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 961cfe5744fSMatthew G. Knepley PetscCheck(8*3 == coordSize,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid coordinate closure size %" PetscInt_FMT " should be %d", coordSize, 8*3); 9625f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, NULL, xLocal, c, &xSize, &x)); 963cfe5744fSMatthew G. Knepley PetscCheck((8*ctx->dof == xSize) || (ctx->dof == xSize),ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input closure size %" PetscInt_FMT " should be %" PetscInt_FMT " or %" PetscInt_FMT, xSize, 8*ctx->dof, ctx->dof); 9645f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetFunction(snes, NULL, NULL, vertices)); 9655f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetJacobian(snes, NULL, NULL, NULL, vertices)); 9665f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(real, &xi)); 967552f7358SJed Brown xi[0] = coords[p*ctx->dim+0]; 968552f7358SJed Brown xi[1] = coords[p*ctx->dim+1]; 969552f7358SJed Brown xi[2] = coords[p*ctx->dim+2]; 9705f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(real, &xi)); 9715f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSolve(snes, real, ref)); 9725f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(ref, &xi)); 973cb313848SJed Brown xir[0] = PetscRealPart(xi[0]); 974cb313848SJed Brown xir[1] = PetscRealPart(xi[1]); 975cb313848SJed Brown xir[2] = PetscRealPart(xi[2]); 976cfe5744fSMatthew G. Knepley if (8*ctx->dof == xSize) { 977552f7358SJed Brown for (comp = 0; comp < ctx->dof; ++comp) { 978552f7358SJed Brown a[p*ctx->dof+comp] = 979cb313848SJed Brown x[0*ctx->dof+comp]*(1-xir[0])*(1-xir[1])*(1-xir[2]) + 9807a1931ceSMatthew G. Knepley x[3*ctx->dof+comp]* xir[0]*(1-xir[1])*(1-xir[2]) + 981cb313848SJed Brown x[2*ctx->dof+comp]* xir[0]* xir[1]*(1-xir[2]) + 9827a1931ceSMatthew G. Knepley x[1*ctx->dof+comp]*(1-xir[0])* xir[1]*(1-xir[2]) + 983cb313848SJed Brown x[4*ctx->dof+comp]*(1-xir[0])*(1-xir[1])* xir[2] + 984cb313848SJed Brown x[5*ctx->dof+comp]* xir[0]*(1-xir[1])* xir[2] + 985cb313848SJed Brown x[6*ctx->dof+comp]* xir[0]* xir[1]* xir[2] + 986cb313848SJed Brown x[7*ctx->dof+comp]*(1-xir[0])* xir[1]* xir[2]; 987552f7358SJed Brown } 988cfe5744fSMatthew G. Knepley } else { 989cfe5744fSMatthew G. Knepley for (comp = 0; comp < ctx->dof; ++comp) a[p*ctx->dof+comp] = x[0*ctx->dof+comp]; 990cfe5744fSMatthew G. Knepley } 9915f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(ref, &xi)); 9925f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dmCoord, NULL, coordsLocal, c, &coordSize, &vertices)); 9935f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, xLocal, c, &xSize, &x)); 994552f7358SJed Brown } 9955f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(v, &a)); 9965f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(ctx->coords, &coords)); 997552f7358SJed Brown 9985f80ce2aSJacob Faibussowitsch CHKERRQ(SNESDestroy(&snes)); 9995f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&r)); 10005f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ref)); 10015f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&real)); 10025f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&J)); 1003552f7358SJed Brown PetscFunctionReturn(0); 1004552f7358SJed Brown } 1005552f7358SJed Brown 10064267b1a3SMatthew G. Knepley /*@C 10074267b1a3SMatthew G. Knepley DMInterpolationEvaluate - Using the input from dm and x, calculates interpolated field values at the interpolation points. 10084267b1a3SMatthew G. Knepley 1009552f7358SJed Brown Input Parameters: 1010552f7358SJed Brown + ctx - The DMInterpolationInfo context 1011552f7358SJed Brown . dm - The DM 1012552f7358SJed Brown - x - The local vector containing the field to be interpolated 1013552f7358SJed Brown 1014552f7358SJed Brown Output Parameters: 1015552f7358SJed Brown . v - The vector containing the interpolated values 10164267b1a3SMatthew G. Knepley 10174267b1a3SMatthew G. Knepley Note: A suitable v can be obtained using DMInterpolationGetVector(). 10184267b1a3SMatthew G. Knepley 10194267b1a3SMatthew G. Knepley Level: beginner 10204267b1a3SMatthew G. Knepley 10214267b1a3SMatthew G. Knepley .seealso: DMInterpolationGetVector(), DMInterpolationAddPoints(), DMInterpolationCreate() 10224267b1a3SMatthew G. Knepley @*/ 10230adebc6cSBarry Smith PetscErrorCode DMInterpolationEvaluate(DMInterpolationInfo ctx, DM dm, Vec x, Vec v) 10240adebc6cSBarry Smith { 102566a0a883SMatthew G. Knepley PetscDS ds; 102666a0a883SMatthew G. Knepley PetscInt n, p, Nf, field; 102766a0a883SMatthew G. Knepley PetscBool useDS = PETSC_FALSE; 1028552f7358SJed Brown 1029552f7358SJed Brown PetscFunctionBegin; 1030552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1031552f7358SJed Brown PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 1032552f7358SJed Brown PetscValidHeaderSpecific(v, VEC_CLASSID, 4); 10335f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(v, &n)); 10342c71b3e2SJacob Faibussowitsch PetscCheckFalse(n != ctx->n*ctx->dof,ctx->comm, PETSC_ERR_ARG_SIZ, "Invalid input vector size %D should be %D", n, ctx->n*ctx->dof); 103566a0a883SMatthew G. Knepley if (!n) PetscFunctionReturn(0); 10365f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm, &ds)); 1037680d18d5SMatthew G. Knepley if (ds) { 103866a0a883SMatthew G. Knepley useDS = PETSC_TRUE; 10395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds, &Nf)); 1040680d18d5SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 104166a0a883SMatthew G. Knepley PetscObject obj; 1042680d18d5SMatthew G. Knepley PetscClassId id; 1043680d18d5SMatthew G. Knepley 10445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(ds, field, &obj)); 10455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetClassId(obj, &id)); 104666a0a883SMatthew G. Knepley if (id != PETSCFE_CLASSID) {useDS = PETSC_FALSE; break;} 104766a0a883SMatthew G. Knepley } 104866a0a883SMatthew G. Knepley } 104966a0a883SMatthew G. Knepley if (useDS) { 105066a0a883SMatthew G. Knepley const PetscScalar *coords; 105166a0a883SMatthew G. Knepley PetscScalar *interpolant; 105266a0a883SMatthew G. Knepley PetscInt cdim, d; 105366a0a883SMatthew G. Knepley 10545f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetCoordinateDim(dm, &cdim)); 10555f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(ctx->coords, &coords)); 10565f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayWrite(v, &interpolant)); 1057680d18d5SMatthew G. Knepley for (p = 0; p < ctx->n; ++p) { 105866a0a883SMatthew G. Knepley PetscReal pcoords[3], xi[3]; 1059680d18d5SMatthew G. Knepley PetscScalar *xa = NULL; 106066a0a883SMatthew G. Knepley PetscInt coff = 0, foff = 0, clSize; 1061680d18d5SMatthew G. Knepley 106252aa1562SMatthew G. Knepley if (ctx->cells[p] < 0) continue; 1063680d18d5SMatthew G. Knepley for (d = 0; d < cdim; ++d) pcoords[d] = PetscRealPart(coords[p*cdim+d]); 10645f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCoordinatesToReference(dm, ctx->cells[p], 1, pcoords, xi)); 10655f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecGetClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa)); 106666a0a883SMatthew G. Knepley for (field = 0; field < Nf; ++field) { 106766a0a883SMatthew G. Knepley PetscTabulation T; 106866a0a883SMatthew G. Knepley PetscFE fe; 106966a0a883SMatthew G. Knepley 10705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetDiscretization(ds, field, (PetscObject *) &fe)); 10715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateTabulation(fe, 1, 1, xi, 0, &T)); 1072680d18d5SMatthew G. Knepley { 1073680d18d5SMatthew G. Knepley const PetscReal *basis = T->T[0]; 1074680d18d5SMatthew G. Knepley const PetscInt Nb = T->Nb; 1075680d18d5SMatthew G. Knepley const PetscInt Nc = T->Nc; 107666a0a883SMatthew G. Knepley PetscInt f, fc; 107766a0a883SMatthew G. Knepley 1078680d18d5SMatthew G. Knepley for (fc = 0; fc < Nc; ++fc) { 107966a0a883SMatthew G. Knepley interpolant[p*ctx->dof+coff+fc] = 0.0; 1080680d18d5SMatthew G. Knepley for (f = 0; f < Nb; ++f) { 108166a0a883SMatthew G. Knepley interpolant[p*ctx->dof+coff+fc] += xa[foff+f]*basis[(0*Nb + f)*Nc + fc]; 1082552f7358SJed Brown } 1083680d18d5SMatthew G. Knepley } 108466a0a883SMatthew G. Knepley coff += Nc; 108566a0a883SMatthew G. Knepley foff += Nb; 1086680d18d5SMatthew G. Knepley } 10875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTabulationDestroy(&T)); 1088680d18d5SMatthew G. Knepley } 10895f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexVecRestoreClosure(dm, NULL, x, ctx->cells[p], &clSize, &xa)); 10902c71b3e2SJacob Faibussowitsch PetscCheckFalse(coff != ctx->dof,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total components %D != %D dof specified for interpolation", coff, ctx->dof); 10912c71b3e2SJacob Faibussowitsch PetscCheckFalse(foff != clSize,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Total FE space size %D != %D closure size", foff, clSize); 109266a0a883SMatthew G. Knepley } 10935f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(ctx->coords, &coords)); 10945f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayWrite(v, &interpolant)); 109566a0a883SMatthew G. Knepley } else { 109666a0a883SMatthew G. Knepley DMPolytopeType ct; 109766a0a883SMatthew G. Knepley 1098680d18d5SMatthew G. Knepley /* TODO Check each cell individually */ 10995f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetCellType(dm, ctx->cells[0], &ct)); 1100680d18d5SMatthew G. Knepley switch (ct) { 11015f80ce2aSJacob Faibussowitsch case DM_POLYTOPE_SEGMENT: CHKERRQ(DMInterpolate_Segment_Private(ctx, dm, x, v));break; 11025f80ce2aSJacob Faibussowitsch case DM_POLYTOPE_TRIANGLE: CHKERRQ(DMInterpolate_Triangle_Private(ctx, dm, x, v));break; 11035f80ce2aSJacob Faibussowitsch case DM_POLYTOPE_QUADRILATERAL: CHKERRQ(DMInterpolate_Quad_Private(ctx, dm, x, v));break; 11045f80ce2aSJacob Faibussowitsch case DM_POLYTOPE_TETRAHEDRON: CHKERRQ(DMInterpolate_Tetrahedron_Private(ctx, dm, x, v));break; 11055f80ce2aSJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: CHKERRQ(DMInterpolate_Hex_Private(ctx, dm, x, v));break; 1106cfe5744fSMatthew G. Knepley default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for cell type %s", DMPolytopeTypes[PetscMax(0, PetscMin(ct, DM_NUM_POLYTOPES))]); 1107680d18d5SMatthew G. Knepley } 1108552f7358SJed Brown } 1109552f7358SJed Brown PetscFunctionReturn(0); 1110552f7358SJed Brown } 1111552f7358SJed Brown 11124267b1a3SMatthew G. Knepley /*@C 11134267b1a3SMatthew G. Knepley DMInterpolationDestroy - Destroys a DMInterpolationInfo context 11144267b1a3SMatthew G. Knepley 11154267b1a3SMatthew G. Knepley Collective on ctx 11164267b1a3SMatthew G. Knepley 11174267b1a3SMatthew G. Knepley Input Parameter: 11184267b1a3SMatthew G. Knepley . ctx - the context 11194267b1a3SMatthew G. Knepley 11204267b1a3SMatthew G. Knepley Level: beginner 11214267b1a3SMatthew G. Knepley 11224267b1a3SMatthew G. Knepley .seealso: DMInterpolationEvaluate(), DMInterpolationAddPoints(), DMInterpolationCreate() 11234267b1a3SMatthew G. Knepley @*/ 11240adebc6cSBarry Smith PetscErrorCode DMInterpolationDestroy(DMInterpolationInfo *ctx) 11250adebc6cSBarry Smith { 1126552f7358SJed Brown PetscFunctionBegin; 1127064a246eSJacob Faibussowitsch PetscValidPointer(ctx, 1); 11285f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&(*ctx)->coords)); 11295f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*ctx)->points)); 11305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree((*ctx)->cells)); 11315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(*ctx)); 11320298fd71SBarry Smith *ctx = NULL; 1133552f7358SJed Brown PetscFunctionReturn(0); 1134552f7358SJed Brown } 1135cc0c4584SMatthew G. Knepley 1136cc0c4584SMatthew G. Knepley /*@C 1137cc0c4584SMatthew G. Knepley SNESMonitorFields - Monitors the residual for each field separately 1138cc0c4584SMatthew G. Knepley 1139cc0c4584SMatthew G. Knepley Collective on SNES 1140cc0c4584SMatthew G. Knepley 1141cc0c4584SMatthew G. Knepley Input Parameters: 1142cc0c4584SMatthew G. Knepley + snes - the SNES context 1143cc0c4584SMatthew G. Knepley . its - iteration number 1144cc0c4584SMatthew G. Knepley . fgnorm - 2-norm of residual 1145d43b4f6eSBarry Smith - vf - PetscViewerAndFormat of type ASCII 1146cc0c4584SMatthew G. Knepley 1147cc0c4584SMatthew G. Knepley Notes: 1148cc0c4584SMatthew G. Knepley This routine prints the residual norm at each iteration. 1149cc0c4584SMatthew G. Knepley 1150cc0c4584SMatthew G. Knepley Level: intermediate 1151cc0c4584SMatthew G. Knepley 1152cc0c4584SMatthew G. Knepley .seealso: SNESMonitorSet(), SNESMonitorDefault() 1153cc0c4584SMatthew G. Knepley @*/ 1154d43b4f6eSBarry Smith PetscErrorCode SNESMonitorFields(SNES snes, PetscInt its, PetscReal fgnorm, PetscViewerAndFormat *vf) 1155cc0c4584SMatthew G. Knepley { 1156d43b4f6eSBarry Smith PetscViewer viewer = vf->viewer; 1157cc0c4584SMatthew G. Knepley Vec res; 1158cc0c4584SMatthew G. Knepley DM dm; 1159cc0c4584SMatthew G. Knepley PetscSection s; 1160cc0c4584SMatthew G. Knepley const PetscScalar *r; 1161cc0c4584SMatthew G. Knepley PetscReal *lnorms, *norms; 1162cc0c4584SMatthew G. Knepley PetscInt numFields, f, pStart, pEnd, p; 1163cc0c4584SMatthew G. Knepley 1164cc0c4584SMatthew G. Knepley PetscFunctionBegin; 11654d4332d5SBarry Smith PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,4); 11665f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetFunction(snes, &res, NULL, NULL)); 11675f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes, &dm)); 11685f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm, &s)); 11695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetNumFields(s, &numFields)); 11705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetChart(s, &pStart, &pEnd)); 11715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc2(numFields, &lnorms, numFields, &norms)); 11725f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(res, &r)); 1173cc0c4584SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 1174cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 1175cc0c4584SMatthew G. Knepley PetscInt fdof, foff, d; 1176cc0c4584SMatthew G. Knepley 11775f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldDof(s, p, f, &fdof)); 11785f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetFieldOffset(s, p, f, &foff)); 1179cc0c4584SMatthew G. Knepley for (d = 0; d < fdof; ++d) lnorms[f] += PetscRealPart(PetscSqr(r[foff+d])); 1180cc0c4584SMatthew G. Knepley } 1181cc0c4584SMatthew G. Knepley } 11825f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(res, &r)); 11835f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(lnorms, norms, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm))); 11845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPushFormat(viewer,vf->format)); 11855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIAddTab(viewer, ((PetscObject) snes)->tablevel)); 11865f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%3D SNES Function norm %14.12e [", its, (double) fgnorm)); 1187cc0c4584SMatthew G. Knepley for (f = 0; f < numFields; ++f) { 11885f80ce2aSJacob Faibussowitsch if (f > 0) CHKERRQ(PetscViewerASCIIPrintf(viewer, ", ")); 11895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "%14.12e", (double) PetscSqrtReal(norms[f]))); 1190cc0c4584SMatthew G. Knepley } 11915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer, "]\n")); 11925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIISubtractTab(viewer, ((PetscObject) snes)->tablevel)); 11935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerPopFormat(viewer)); 11945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(lnorms, norms)); 1195cc0c4584SMatthew G. Knepley PetscFunctionReturn(0); 1196cc0c4584SMatthew G. Knepley } 119724cdb843SMatthew G. Knepley 119824cdb843SMatthew G. Knepley /********************* Residual Computation **************************/ 119924cdb843SMatthew G. Knepley 12006528b96dSMatthew G. Knepley PetscErrorCode DMPlexGetAllCells_Internal(DM plex, IS *cellIS) 12016528b96dSMatthew G. Knepley { 12026528b96dSMatthew G. Knepley PetscInt depth; 12036528b96dSMatthew G. Knepley 12046528b96dSMatthew G. Knepley PetscFunctionBegin; 12055f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetDepth(plex, &depth)); 12065f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetStratumIS(plex, "dim", depth, cellIS)); 12075f80ce2aSJacob Faibussowitsch if (!*cellIS) CHKERRQ(DMGetStratumIS(plex, "depth", depth, cellIS)); 12086528b96dSMatthew G. Knepley PetscFunctionReturn(0); 12096528b96dSMatthew G. Knepley } 12106528b96dSMatthew G. Knepley 121124cdb843SMatthew G. Knepley /*@ 12128db23a53SJed Brown DMPlexSNESComputeResidualFEM - Sums the local residual into vector F from the local input X using pointwise functions specified by the user 121324cdb843SMatthew G. Knepley 121424cdb843SMatthew G. Knepley Input Parameters: 121524cdb843SMatthew G. Knepley + dm - The mesh 121624cdb843SMatthew G. Knepley . X - Local solution 121724cdb843SMatthew G. Knepley - user - The user context 121824cdb843SMatthew G. Knepley 121924cdb843SMatthew G. Knepley Output Parameter: 122024cdb843SMatthew G. Knepley . F - Local output vector 122124cdb843SMatthew G. Knepley 12228db23a53SJed Brown Notes: 12238db23a53SJed Brown The residual is summed into F; the caller is responsible for using VecZeroEntries() or otherwise ensuring that any data in F is intentional. 12248db23a53SJed Brown 122524cdb843SMatthew G. Knepley Level: developer 122624cdb843SMatthew G. Knepley 12277a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 122824cdb843SMatthew G. Knepley @*/ 122924cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 123024cdb843SMatthew G. Knepley { 12316da023fcSToby Isaac DM plex; 1232083401c6SMatthew G. Knepley IS allcellIS; 12336528b96dSMatthew G. Knepley PetscInt Nds, s; 123424cdb843SMatthew G. Knepley 123524cdb843SMatthew G. Knepley PetscFunctionBegin; 12365f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESConvertPlex(dm, &plex, PETSC_TRUE)); 12375f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAllCells_Internal(plex, &allcellIS)); 12385f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumDS(dm, &Nds)); 12396528b96dSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 12406528b96dSMatthew G. Knepley PetscDS ds; 12416528b96dSMatthew G. Knepley IS cellIS; 124206ad1575SMatthew G. Knepley PetscFormKey key; 12436528b96dSMatthew G. Knepley 12445f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetRegionNumDS(dm, s, &key.label, NULL, &ds)); 12456528b96dSMatthew G. Knepley key.value = 0; 12466528b96dSMatthew G. Knepley key.field = 0; 124706ad1575SMatthew G. Knepley key.part = 0; 12486528b96dSMatthew G. Knepley if (!key.label) { 12495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) allcellIS)); 12506528b96dSMatthew G. Knepley cellIS = allcellIS; 12516528b96dSMatthew G. Knepley } else { 12526528b96dSMatthew G. Knepley IS pointIS; 12536528b96dSMatthew G. Knepley 12546528b96dSMatthew G. Knepley key.value = 1; 12555f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(key.label, key.value, &pointIS)); 12565f80ce2aSJacob Faibussowitsch CHKERRQ(ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS)); 12575f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 12586528b96dSMatthew G. Knepley } 12595f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeResidual_Internal(plex, key, cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user)); 12605f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellIS)); 12616528b96dSMatthew G. Knepley } 12625f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&allcellIS)); 12635f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&plex)); 12646528b96dSMatthew G. Knepley PetscFunctionReturn(0); 12656528b96dSMatthew G. Knepley } 12666528b96dSMatthew G. Knepley 12676528b96dSMatthew G. Knepley PetscErrorCode DMSNESComputeResidual(DM dm, Vec X, Vec F, void *user) 12686528b96dSMatthew G. Knepley { 12696528b96dSMatthew G. Knepley DM plex; 12706528b96dSMatthew G. Knepley IS allcellIS; 12716528b96dSMatthew G. Knepley PetscInt Nds, s; 12726528b96dSMatthew G. Knepley 12736528b96dSMatthew G. Knepley PetscFunctionBegin; 12745f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESConvertPlex(dm, &plex, PETSC_TRUE)); 12755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAllCells_Internal(plex, &allcellIS)); 12765f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumDS(dm, &Nds)); 1277083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1278083401c6SMatthew G. Knepley PetscDS ds; 1279083401c6SMatthew G. Knepley DMLabel label; 1280083401c6SMatthew G. Knepley IS cellIS; 1281083401c6SMatthew G. Knepley 12825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetRegionNumDS(dm, s, &label, NULL, &ds)); 12836528b96dSMatthew G. Knepley { 128406ad1575SMatthew G. Knepley PetscWeakFormKind resmap[2] = {PETSC_WF_F0, PETSC_WF_F1}; 12856528b96dSMatthew G. Knepley PetscWeakForm wf; 12866528b96dSMatthew G. Knepley PetscInt Nm = 2, m, Nk = 0, k, kp, off = 0; 128706ad1575SMatthew G. Knepley PetscFormKey *reskeys; 12886528b96dSMatthew G. Knepley 12896528b96dSMatthew G. Knepley /* Get unique residual keys */ 12906528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 12916528b96dSMatthew G. Knepley PetscInt Nkm; 12925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapFormGetSize(ds->wf->form[resmap[m]], &Nkm)); 12936528b96dSMatthew G. Knepley Nk += Nkm; 12946528b96dSMatthew G. Knepley } 12955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Nk, &reskeys)); 12966528b96dSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 12975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapFormGetKeys(ds->wf->form[resmap[m]], &off, reskeys)); 12986528b96dSMatthew G. Knepley } 12992c71b3e2SJacob Faibussowitsch PetscCheckFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk); 13005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFormKeySort(Nk, reskeys)); 13016528b96dSMatthew G. Knepley for (k = 0, kp = 1; kp < Nk; ++kp) { 13026528b96dSMatthew G. Knepley if ((reskeys[k].label != reskeys[kp].label) || (reskeys[k].value != reskeys[kp].value)) { 13036528b96dSMatthew G. Knepley ++k; 13046528b96dSMatthew G. Knepley if (kp != k) reskeys[k] = reskeys[kp]; 13056528b96dSMatthew G. Knepley } 13066528b96dSMatthew G. Knepley } 13076528b96dSMatthew G. Knepley Nk = k; 13086528b96dSMatthew G. Knepley 13095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetWeakForm(ds, &wf)); 13106528b96dSMatthew G. Knepley for (k = 0; k < Nk; ++k) { 13116528b96dSMatthew G. Knepley DMLabel label = reskeys[k].label; 13126528b96dSMatthew G. Knepley PetscInt val = reskeys[k].value; 13136528b96dSMatthew G. Knepley 1314083401c6SMatthew G. Knepley if (!label) { 13155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) allcellIS)); 1316083401c6SMatthew G. Knepley cellIS = allcellIS; 1317083401c6SMatthew G. Knepley } else { 1318083401c6SMatthew G. Knepley IS pointIS; 1319083401c6SMatthew G. Knepley 13205f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(label, val, &pointIS)); 13215f80ce2aSJacob Faibussowitsch CHKERRQ(ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS)); 13225f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 13234a3e9fdbSToby Isaac } 13245f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeResidual_Internal(plex, reskeys[k], cellIS, PETSC_MIN_REAL, X, NULL, 0.0, F, user)); 13255f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellIS)); 1326083401c6SMatthew G. Knepley } 13275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(reskeys)); 13286528b96dSMatthew G. Knepley } 13296528b96dSMatthew G. Knepley } 13305f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&allcellIS)); 13315f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&plex)); 133224cdb843SMatthew G. Knepley PetscFunctionReturn(0); 133324cdb843SMatthew G. Knepley } 133424cdb843SMatthew G. Knepley 1335bdd6f66aSToby Isaac /*@ 1336bdd6f66aSToby Isaac DMPlexSNESComputeBoundaryFEM - Form the boundary values for the local input X 1337bdd6f66aSToby Isaac 1338bdd6f66aSToby Isaac Input Parameters: 1339bdd6f66aSToby Isaac + dm - The mesh 1340bdd6f66aSToby Isaac - user - The user context 1341bdd6f66aSToby Isaac 1342bdd6f66aSToby Isaac Output Parameter: 1343bdd6f66aSToby Isaac . X - Local solution 1344bdd6f66aSToby Isaac 1345bdd6f66aSToby Isaac Level: developer 1346bdd6f66aSToby Isaac 13477a73cf09SMatthew G. Knepley .seealso: DMPlexComputeJacobianAction() 1348bdd6f66aSToby Isaac @*/ 1349bdd6f66aSToby Isaac PetscErrorCode DMPlexSNESComputeBoundaryFEM(DM dm, Vec X, void *user) 1350bdd6f66aSToby Isaac { 1351bdd6f66aSToby Isaac DM plex; 1352bdd6f66aSToby Isaac 1353bdd6f66aSToby Isaac PetscFunctionBegin; 13545f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESConvertPlex(dm,&plex,PETSC_TRUE)); 13555f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexInsertBoundaryValues(plex, PETSC_TRUE, X, PETSC_MIN_REAL, NULL, NULL, NULL)); 13565f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&plex)); 1357bdd6f66aSToby Isaac PetscFunctionReturn(0); 1358bdd6f66aSToby Isaac } 1359bdd6f66aSToby Isaac 13607a73cf09SMatthew G. Knepley /*@ 13618e3a2eefSMatthew G. Knepley DMSNESComputeJacobianAction - Compute the action of the Jacobian J(X) on Y 13627a73cf09SMatthew G. Knepley 13637a73cf09SMatthew G. Knepley Input Parameters: 13648e3a2eefSMatthew G. Knepley + dm - The DM 13657a73cf09SMatthew G. Knepley . X - Local solution vector 13667a73cf09SMatthew G. Knepley . Y - Local input vector 13677a73cf09SMatthew G. Knepley - user - The user context 13687a73cf09SMatthew G. Knepley 13697a73cf09SMatthew G. Knepley Output Parameter: 13708e3a2eefSMatthew G. Knepley . F - lcoal output vector 13717a73cf09SMatthew G. Knepley 13727a73cf09SMatthew G. Knepley Level: developer 13737a73cf09SMatthew G. Knepley 13748e3a2eefSMatthew G. Knepley Notes: 13758e3a2eefSMatthew G. Knepley Users will typically use DMSNESCreateJacobianMF() followed by MatMult() instead of calling this routine directly. 13768e3a2eefSMatthew G. Knepley 1377a509fe9cSSatish Balay .seealso: DMSNESCreateJacobianMF(), DMPlexSNESComputeResidualFEM() 13787a73cf09SMatthew G. Knepley @*/ 13798e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESComputeJacobianAction(DM dm, Vec X, Vec Y, Vec F, void *user) 1380a925c78cSMatthew G. Knepley { 13818e3a2eefSMatthew G. Knepley DM plex; 13828e3a2eefSMatthew G. Knepley IS allcellIS; 13838e3a2eefSMatthew G. Knepley PetscInt Nds, s; 1384a925c78cSMatthew G. Knepley 1385a925c78cSMatthew G. Knepley PetscFunctionBegin; 13865f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESConvertPlex(dm, &plex, PETSC_TRUE)); 13875f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAllCells_Internal(plex, &allcellIS)); 13885f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumDS(dm, &Nds)); 13898e3a2eefSMatthew G. Knepley for (s = 0; s < Nds; ++s) { 13908e3a2eefSMatthew G. Knepley PetscDS ds; 13918e3a2eefSMatthew G. Knepley DMLabel label; 13928e3a2eefSMatthew G. Knepley IS cellIS; 13937a73cf09SMatthew G. Knepley 13945f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetRegionNumDS(dm, s, &label, NULL, &ds)); 13958e3a2eefSMatthew G. Knepley { 139606ad1575SMatthew G. Knepley PetscWeakFormKind jacmap[4] = {PETSC_WF_G0, PETSC_WF_G1, PETSC_WF_G2, PETSC_WF_G3}; 13978e3a2eefSMatthew G. Knepley PetscWeakForm wf; 13988e3a2eefSMatthew G. Knepley PetscInt Nm = 4, m, Nk = 0, k, kp, off = 0; 139906ad1575SMatthew G. Knepley PetscFormKey *jackeys; 14008e3a2eefSMatthew G. Knepley 14018e3a2eefSMatthew G. Knepley /* Get unique Jacobian keys */ 14028e3a2eefSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 14038e3a2eefSMatthew G. Knepley PetscInt Nkm; 14045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapFormGetSize(ds->wf->form[jacmap[m]], &Nkm)); 14058e3a2eefSMatthew G. Knepley Nk += Nkm; 14068e3a2eefSMatthew G. Knepley } 14075f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(Nk, &jackeys)); 14088e3a2eefSMatthew G. Knepley for (m = 0; m < Nm; ++m) { 14095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscHMapFormGetKeys(ds->wf->form[jacmap[m]], &off, jackeys)); 14108e3a2eefSMatthew G. Knepley } 14112c71b3e2SJacob Faibussowitsch PetscCheckFalse(off != Nk,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of keys %D should be %D", off, Nk); 14125f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFormKeySort(Nk, jackeys)); 14138e3a2eefSMatthew G. Knepley for (k = 0, kp = 1; kp < Nk; ++kp) { 14148e3a2eefSMatthew G. Knepley if ((jackeys[k].label != jackeys[kp].label) || (jackeys[k].value != jackeys[kp].value)) { 14158e3a2eefSMatthew G. Knepley ++k; 14168e3a2eefSMatthew G. Knepley if (kp != k) jackeys[k] = jackeys[kp]; 14178e3a2eefSMatthew G. Knepley } 14188e3a2eefSMatthew G. Knepley } 14198e3a2eefSMatthew G. Knepley Nk = k; 14208e3a2eefSMatthew G. Knepley 14215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetWeakForm(ds, &wf)); 14228e3a2eefSMatthew G. Knepley for (k = 0; k < Nk; ++k) { 14238e3a2eefSMatthew G. Knepley DMLabel label = jackeys[k].label; 14248e3a2eefSMatthew G. Knepley PetscInt val = jackeys[k].value; 14258e3a2eefSMatthew G. Knepley 14268e3a2eefSMatthew G. Knepley if (!label) { 14275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) allcellIS)); 14288e3a2eefSMatthew G. Knepley cellIS = allcellIS; 14297a73cf09SMatthew G. Knepley } else { 14308e3a2eefSMatthew G. Knepley IS pointIS; 1431a925c78cSMatthew G. Knepley 14325f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(label, val, &pointIS)); 14335f80ce2aSJacob Faibussowitsch CHKERRQ(ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS)); 14345f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 1435a925c78cSMatthew G. Knepley } 14365f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeJacobian_Action_Internal(plex, jackeys[k], cellIS, 0.0, 0.0, X, NULL, Y, F, user)); 14375f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellIS)); 14388e3a2eefSMatthew G. Knepley } 14395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(jackeys)); 14408e3a2eefSMatthew G. Knepley } 14418e3a2eefSMatthew G. Knepley } 14425f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&allcellIS)); 14435f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&plex)); 1444a925c78cSMatthew G. Knepley PetscFunctionReturn(0); 1445a925c78cSMatthew G. Knepley } 1446a925c78cSMatthew G. Knepley 144724cdb843SMatthew G. Knepley /*@ 144824cdb843SMatthew G. Knepley DMPlexSNESComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 144924cdb843SMatthew G. Knepley 145024cdb843SMatthew G. Knepley Input Parameters: 145124cdb843SMatthew G. Knepley + dm - The mesh 145224cdb843SMatthew G. Knepley . X - Local input vector 145324cdb843SMatthew G. Knepley - user - The user context 145424cdb843SMatthew G. Knepley 145524cdb843SMatthew G. Knepley Output Parameter: 145624cdb843SMatthew G. Knepley . Jac - Jacobian matrix 145724cdb843SMatthew G. Knepley 145824cdb843SMatthew G. Knepley Note: 145924cdb843SMatthew G. Knepley We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 146024cdb843SMatthew G. Knepley like a GPU, or vectorize on a multicore machine. 146124cdb843SMatthew G. Knepley 146224cdb843SMatthew G. Knepley Level: developer 146324cdb843SMatthew G. Knepley 146424cdb843SMatthew G. Knepley .seealso: FormFunctionLocal() 146524cdb843SMatthew G. Knepley @*/ 146624cdb843SMatthew G. Knepley PetscErrorCode DMPlexSNESComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP,void *user) 146724cdb843SMatthew G. Knepley { 14686da023fcSToby Isaac DM plex; 1469083401c6SMatthew G. Knepley IS allcellIS; 1470f04eb4edSMatthew G. Knepley PetscBool hasJac, hasPrec; 14716528b96dSMatthew G. Knepley PetscInt Nds, s; 147224cdb843SMatthew G. Knepley 147324cdb843SMatthew G. Knepley PetscFunctionBegin; 14745f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESConvertPlex(dm, &plex, PETSC_TRUE)); 14755f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexGetAllCells_Internal(plex, &allcellIS)); 14765f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumDS(dm, &Nds)); 1477083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 1478083401c6SMatthew G. Knepley PetscDS ds; 1479083401c6SMatthew G. Knepley IS cellIS; 148006ad1575SMatthew G. Knepley PetscFormKey key; 1481083401c6SMatthew G. Knepley 14825f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetRegionNumDS(dm, s, &key.label, NULL, &ds)); 14836528b96dSMatthew G. Knepley key.value = 0; 14846528b96dSMatthew G. Knepley key.field = 0; 148506ad1575SMatthew G. Knepley key.part = 0; 14866528b96dSMatthew G. Knepley if (!key.label) { 14875f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) allcellIS)); 1488083401c6SMatthew G. Knepley cellIS = allcellIS; 1489083401c6SMatthew G. Knepley } else { 1490083401c6SMatthew G. Knepley IS pointIS; 1491083401c6SMatthew G. Knepley 14926528b96dSMatthew G. Knepley key.value = 1; 14935f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(key.label, key.value, &pointIS)); 14945f80ce2aSJacob Faibussowitsch CHKERRQ(ISIntersect_Caching_Internal(allcellIS, pointIS, &cellIS)); 14955f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&pointIS)); 1496083401c6SMatthew G. Knepley } 1497083401c6SMatthew G. Knepley if (!s) { 14985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSHasJacobian(ds, &hasJac)); 14995f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSHasJacobianPreconditioner(ds, &hasPrec)); 15005f80ce2aSJacob Faibussowitsch if (hasJac && hasPrec) CHKERRQ(MatZeroEntries(Jac)); 15015f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(JacP)); 1502083401c6SMatthew G. Knepley } 15035f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeJacobian_Internal(plex, key, cellIS, 0.0, 0.0, X, NULL, Jac, JacP, user)); 15045f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&cellIS)); 1505083401c6SMatthew G. Knepley } 15065f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&allcellIS)); 15075f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&plex)); 150824cdb843SMatthew G. Knepley PetscFunctionReturn(0); 150924cdb843SMatthew G. Knepley } 15101878804aSMatthew G. Knepley 15118e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx 15128e3a2eefSMatthew G. Knepley { 15138e3a2eefSMatthew G. Knepley DM dm; 15148e3a2eefSMatthew G. Knepley Vec X; 15158e3a2eefSMatthew G. Knepley void *ctx; 15168e3a2eefSMatthew G. Knepley }; 15178e3a2eefSMatthew G. Knepley 15188e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Destroy_Private(Mat A) 15198e3a2eefSMatthew G. Knepley { 15208e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15218e3a2eefSMatthew G. Knepley 15228e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15235f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A, &ctx)); 15245f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetContext(A, NULL)); 15255f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&ctx->dm)); 15265f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ctx->X)); 15275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(ctx)); 15288e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15298e3a2eefSMatthew G. Knepley } 15308e3a2eefSMatthew G. Knepley 15318e3a2eefSMatthew G. Knepley static PetscErrorCode DMSNESJacobianMF_Mult_Private(Mat A, Vec Y, Vec Z) 15328e3a2eefSMatthew G. Knepley { 15338e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15348e3a2eefSMatthew G. Knepley 15358e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15365f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellGetContext(A, &ctx)); 15375f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESComputeJacobianAction(ctx->dm, ctx->X, Y, Z, ctx->ctx)); 15388e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15398e3a2eefSMatthew G. Knepley } 15408e3a2eefSMatthew G. Knepley 15418e3a2eefSMatthew G. Knepley /*@ 15428e3a2eefSMatthew G. Knepley DMSNESCreateJacobianMF - Create a Mat which computes the action of the Jacobian matrix-free 15438e3a2eefSMatthew G. Knepley 15448e3a2eefSMatthew G. Knepley Collective on dm 15458e3a2eefSMatthew G. Knepley 15468e3a2eefSMatthew G. Knepley Input Parameters: 15478e3a2eefSMatthew G. Knepley + dm - The DM 15488e3a2eefSMatthew G. Knepley . X - The evaluation point for the Jacobian 15498e3a2eefSMatthew G. Knepley - user - A user context, or NULL 15508e3a2eefSMatthew G. Knepley 15518e3a2eefSMatthew G. Knepley Output Parameter: 15528e3a2eefSMatthew G. Knepley . J - The Mat 15538e3a2eefSMatthew G. Knepley 15548e3a2eefSMatthew G. Knepley Level: advanced 15558e3a2eefSMatthew G. Knepley 15568e3a2eefSMatthew G. Knepley Notes: 15578e3a2eefSMatthew G. Knepley Vec X is kept in Mat J, so updating X then updates the evaluation point. 15588e3a2eefSMatthew G. Knepley 15598e3a2eefSMatthew G. Knepley .seealso: DMSNESComputeJacobianAction() 15608e3a2eefSMatthew G. Knepley @*/ 15618e3a2eefSMatthew G. Knepley PetscErrorCode DMSNESCreateJacobianMF(DM dm, Vec X, void *user, Mat *J) 15628e3a2eefSMatthew G. Knepley { 15638e3a2eefSMatthew G. Knepley struct _DMSNESJacobianMFCtx *ctx; 15648e3a2eefSMatthew G. Knepley PetscInt n, N; 15658e3a2eefSMatthew G. Knepley 15668e3a2eefSMatthew G. Knepley PetscFunctionBegin; 15675f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject) dm), J)); 15685f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*J, MATSHELL)); 15695f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(X, &n)); 15705f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(X, &N)); 15715f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(*J, n, n, N, N)); 15725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) dm)); 15735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectReference((PetscObject) X)); 15745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(1, &ctx)); 15758e3a2eefSMatthew G. Knepley ctx->dm = dm; 15768e3a2eefSMatthew G. Knepley ctx->X = X; 15778e3a2eefSMatthew G. Knepley ctx->ctx = user; 15785f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetContext(*J, ctx)); 15795f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(*J, MATOP_DESTROY, (void (*)(void)) DMSNESJacobianMF_Destroy_Private)); 15805f80ce2aSJacob Faibussowitsch CHKERRQ(MatShellSetOperation(*J, MATOP_MULT, (void (*)(void)) DMSNESJacobianMF_Mult_Private)); 15818e3a2eefSMatthew G. Knepley PetscFunctionReturn(0); 15828e3a2eefSMatthew G. Knepley } 15838e3a2eefSMatthew G. Knepley 158438cfc46eSPierre Jolivet /* 158538cfc46eSPierre Jolivet MatComputeNeumannOverlap - Computes an unassembled (Neumann) local overlapping Mat in nonlinear context. 158638cfc46eSPierre Jolivet 158738cfc46eSPierre Jolivet Input Parameters: 158838cfc46eSPierre Jolivet + X - SNES linearization point 158938cfc46eSPierre Jolivet . ovl - index set of overlapping subdomains 159038cfc46eSPierre Jolivet 159138cfc46eSPierre Jolivet Output Parameter: 159238cfc46eSPierre Jolivet . J - unassembled (Neumann) local matrix 159338cfc46eSPierre Jolivet 159438cfc46eSPierre Jolivet Level: intermediate 159538cfc46eSPierre Jolivet 159638cfc46eSPierre Jolivet .seealso: DMCreateNeumannOverlap(), MATIS, PCHPDDMSetAuxiliaryMat() 159738cfc46eSPierre Jolivet */ 159838cfc46eSPierre Jolivet static PetscErrorCode MatComputeNeumannOverlap_Plex(Mat J, PetscReal t, Vec X, Vec X_t, PetscReal s, IS ovl, void *ctx) 159938cfc46eSPierre Jolivet { 160038cfc46eSPierre Jolivet SNES snes; 160138cfc46eSPierre Jolivet Mat pJ; 160238cfc46eSPierre Jolivet DM ovldm,origdm; 160338cfc46eSPierre Jolivet DMSNES sdm; 160438cfc46eSPierre Jolivet PetscErrorCode (*bfun)(DM,Vec,void*); 160538cfc46eSPierre Jolivet PetscErrorCode (*jfun)(DM,Vec,Mat,Mat,void*); 160638cfc46eSPierre Jolivet void *bctx,*jctx; 160738cfc46eSPierre Jolivet 160838cfc46eSPierre Jolivet PetscFunctionBegin; 16095f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_MATIS",(PetscObject*)&pJ)); 1610*28b400f6SJacob Faibussowitsch PetscCheck(pJ,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing overlapping Mat"); 16115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)ovl,"_DM_Original_HPDDM",(PetscObject*)&origdm)); 1612*28b400f6SJacob Faibussowitsch PetscCheck(origdm,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing original DM"); 16135f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDM(pJ,&ovldm)); 16145f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESGetBoundaryLocal(origdm,&bfun,&bctx)); 16155f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESSetBoundaryLocal(ovldm,bfun,bctx)); 16165f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESGetJacobianLocal(origdm,&jfun,&jctx)); 16175f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESSetJacobianLocal(ovldm,jfun,jctx)); 16185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject*)&snes)); 161938cfc46eSPierre Jolivet if (!snes) { 16205f80ce2aSJacob Faibussowitsch CHKERRQ(SNESCreate(PetscObjectComm((PetscObject)ovl),&snes)); 16215f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetDM(snes,ovldm)); 16225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectCompose((PetscObject)ovl,"_DM_Overlap_HPDDM_SNES",(PetscObject)snes)); 16235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectDereference((PetscObject)snes)); 162438cfc46eSPierre Jolivet } 16255f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDMSNES(ovldm,&sdm)); 16265f80ce2aSJacob Faibussowitsch CHKERRQ(VecLockReadPush(X)); 162738cfc46eSPierre Jolivet PetscStackPush("SNES user Jacobian function"); 16285f80ce2aSJacob Faibussowitsch CHKERRQ((*sdm->ops->computejacobian)(snes,X,pJ,pJ,sdm->jacobianctx)); 162938cfc46eSPierre Jolivet PetscStackPop; 16305f80ce2aSJacob Faibussowitsch CHKERRQ(VecLockReadPop(X)); 163138cfc46eSPierre Jolivet /* this is a no-hop, just in case we decide to change the placeholder for the local Neumann matrix */ 163238cfc46eSPierre Jolivet { 163338cfc46eSPierre Jolivet Mat locpJ; 163438cfc46eSPierre Jolivet 16355f80ce2aSJacob Faibussowitsch CHKERRQ(MatISGetLocalMat(pJ,&locpJ)); 16365f80ce2aSJacob Faibussowitsch CHKERRQ(MatCopy(locpJ,J,SAME_NONZERO_PATTERN)); 163738cfc46eSPierre Jolivet } 163838cfc46eSPierre Jolivet PetscFunctionReturn(0); 163938cfc46eSPierre Jolivet } 164038cfc46eSPierre Jolivet 1641a925c78cSMatthew G. Knepley /*@ 16429f520fc2SToby Isaac DMPlexSetSNESLocalFEM - Use DMPlex's internal FEM routines to compute SNES boundary values, residual, and Jacobian. 16439f520fc2SToby Isaac 16449f520fc2SToby Isaac Input Parameters: 16459f520fc2SToby Isaac + dm - The DM object 1646dff059c6SToby Isaac . boundaryctx - the user context that will be passed to pointwise evaluation of boundary values (see PetscDSAddBoundary()) 16479f520fc2SToby Isaac . residualctx - the user context that will be passed to pointwise evaluation of finite element residual computations (see PetscDSSetResidual()) 16489f520fc2SToby Isaac - jacobianctx - the user context that will be passed to pointwise evaluation of finite element Jacobian construction (see PetscDSSetJacobian()) 16491a244344SSatish Balay 16501a244344SSatish Balay Level: developer 16519f520fc2SToby Isaac @*/ 16529f520fc2SToby Isaac PetscErrorCode DMPlexSetSNESLocalFEM(DM dm, void *boundaryctx, void *residualctx, void *jacobianctx) 16539f520fc2SToby Isaac { 16549f520fc2SToby Isaac PetscFunctionBegin; 16555f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESSetBoundaryLocal(dm,DMPlexSNESComputeBoundaryFEM,boundaryctx)); 16565f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESSetFunctionLocal(dm,DMPlexSNESComputeResidualFEM,residualctx)); 16575f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESSetJacobianLocal(dm,DMPlexSNESComputeJacobianFEM,jacobianctx)); 16585f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",MatComputeNeumannOverlap_Plex)); 16599f520fc2SToby Isaac PetscFunctionReturn(0); 16609f520fc2SToby Isaac } 16619f520fc2SToby Isaac 1662f017bcb6SMatthew G. Knepley /*@C 1663f017bcb6SMatthew G. Knepley DMSNESCheckDiscretization - Check the discretization error of the exact solution 1664f017bcb6SMatthew G. Knepley 1665f017bcb6SMatthew G. Knepley Input Parameters: 1666f017bcb6SMatthew G. Knepley + snes - the SNES object 1667f017bcb6SMatthew G. Knepley . dm - the DM 1668f2cacb80SMatthew G. Knepley . t - the time 1669f017bcb6SMatthew G. Knepley . u - a DM vector 1670f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1671f017bcb6SMatthew G. Knepley 1672f3c94560SMatthew G. Knepley Output Parameters: 1673f3c94560SMatthew G. Knepley . error - An array which holds the discretization error in each field, or NULL 1674f3c94560SMatthew G. Knepley 16757f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 16767f96f943SMatthew G. Knepley 1677f017bcb6SMatthew G. Knepley Level: developer 1678f017bcb6SMatthew G. Knepley 16797f96f943SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckResidual(), DMSNESCheckJacobian(), PetscDSSetExactSolution() 1680f017bcb6SMatthew G. Knepley @*/ 1681f2cacb80SMatthew G. Knepley PetscErrorCode DMSNESCheckDiscretization(SNES snes, DM dm, PetscReal t, Vec u, PetscReal tol, PetscReal error[]) 16821878804aSMatthew G. Knepley { 1683f017bcb6SMatthew G. Knepley PetscErrorCode (**exacts)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 1684f017bcb6SMatthew G. Knepley void **ectxs; 1685f3c94560SMatthew G. Knepley PetscReal *err; 16867f96f943SMatthew G. Knepley MPI_Comm comm; 16877f96f943SMatthew G. Knepley PetscInt Nf, f; 16881878804aSMatthew G. Knepley 16891878804aSMatthew G. Knepley PetscFunctionBegin; 1690f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1691f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1692064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(u, VEC_CLASSID, 4); 1693534a8f05SLisandro Dalcin if (error) PetscValidRealPointer(error, 6); 16947f96f943SMatthew G. Knepley 16955f80ce2aSJacob Faibussowitsch CHKERRQ(DMComputeExactSolution(dm, t, u, NULL)); 16965f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(u, NULL, "-vec_view")); 16977f96f943SMatthew G. Knepley 16985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) snes, &comm)); 16995f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumFields(dm, &Nf)); 17005f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc3(Nf, &exacts, Nf, &ectxs, PetscMax(1, Nf), &err)); 17017f96f943SMatthew G. Knepley { 17027f96f943SMatthew G. Knepley PetscInt Nds, s; 17037f96f943SMatthew G. Knepley 17045f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumDS(dm, &Nds)); 1705083401c6SMatthew G. Knepley for (s = 0; s < Nds; ++s) { 17067f96f943SMatthew G. Knepley PetscDS ds; 1707083401c6SMatthew G. Knepley DMLabel label; 1708083401c6SMatthew G. Knepley IS fieldIS; 17097f96f943SMatthew G. Knepley const PetscInt *fields; 17107f96f943SMatthew G. Knepley PetscInt dsNf, f; 1711083401c6SMatthew G. Knepley 17125f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetRegionNumDS(dm, s, &label, &fieldIS, &ds)); 17135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetNumFields(ds, &dsNf)); 17145f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(fieldIS, &fields)); 1715083401c6SMatthew G. Knepley for (f = 0; f < dsNf; ++f) { 1716083401c6SMatthew G. Knepley const PetscInt field = fields[f]; 17175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSGetExactSolution(ds, field, &exacts[field], &ectxs[field])); 1718083401c6SMatthew G. Knepley } 17195f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(fieldIS, &fields)); 1720083401c6SMatthew G. Knepley } 1721083401c6SMatthew G. Knepley } 1722f017bcb6SMatthew G. Knepley if (Nf > 1) { 17235f80ce2aSJacob Faibussowitsch CHKERRQ(DMComputeL2FieldDiff(dm, t, exacts, ectxs, u, err)); 1724f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 1725f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 17262c71b3e2SJacob Faibussowitsch PetscCheckFalse(err[f] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g for field %D exceeds tolerance %g", (double) err[f], f, (double) tol); 17271878804aSMatthew G. Knepley } 1728b878532fSMatthew G. Knepley } else if (error) { 1729b878532fSMatthew G. Knepley for (f = 0; f < Nf; ++f) error[f] = err[f]; 17301878804aSMatthew G. Knepley } else { 17315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "L_2 Error: [")); 1732f017bcb6SMatthew G. Knepley for (f = 0; f < Nf; ++f) { 17335f80ce2aSJacob Faibussowitsch if (f) CHKERRQ(PetscPrintf(comm, ", ")); 17345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "%g", (double)err[f])); 17351878804aSMatthew G. Knepley } 17365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "]\n")); 1737f017bcb6SMatthew G. Knepley } 1738f017bcb6SMatthew G. Knepley } else { 17395f80ce2aSJacob Faibussowitsch CHKERRQ(DMComputeL2Diff(dm, t, exacts, ectxs, u, &err[0])); 1740f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 17412c71b3e2SJacob Faibussowitsch PetscCheckFalse(err[0] > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Error %g exceeds tolerance %g", (double) err[0], (double) tol); 1742b878532fSMatthew G. Knepley } else if (error) { 1743b878532fSMatthew G. Knepley error[0] = err[0]; 1744f017bcb6SMatthew G. Knepley } else { 17455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "L_2 Error: %g\n", (double) err[0])); 1746f017bcb6SMatthew G. Knepley } 1747f017bcb6SMatthew G. Knepley } 17485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(exacts, ectxs, err)); 1749f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1750f017bcb6SMatthew G. Knepley } 1751f017bcb6SMatthew G. Knepley 1752f017bcb6SMatthew G. Knepley /*@C 1753f017bcb6SMatthew G. Knepley DMSNESCheckResidual - Check the residual of the exact solution 1754f017bcb6SMatthew G. Knepley 1755f017bcb6SMatthew G. Knepley Input Parameters: 1756f017bcb6SMatthew G. Knepley + snes - the SNES object 1757f017bcb6SMatthew G. Knepley . dm - the DM 1758f017bcb6SMatthew G. Knepley . u - a DM vector 1759f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1760f017bcb6SMatthew G. Knepley 1761f3c94560SMatthew G. Knepley Output Parameters: 1762f3c94560SMatthew G. Knepley . residual - The residual norm of the exact solution, or NULL 1763f3c94560SMatthew G. Knepley 1764f017bcb6SMatthew G. Knepley Level: developer 1765f017bcb6SMatthew G. Knepley 1766f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckJacobian() 1767f017bcb6SMatthew G. Knepley @*/ 1768f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckResidual(SNES snes, DM dm, Vec u, PetscReal tol, PetscReal *residual) 1769f017bcb6SMatthew G. Knepley { 1770f017bcb6SMatthew G. Knepley MPI_Comm comm; 1771f017bcb6SMatthew G. Knepley Vec r; 1772f017bcb6SMatthew G. Knepley PetscReal res; 1773f017bcb6SMatthew G. Knepley 1774f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1775f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1776f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1777f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1778534a8f05SLisandro Dalcin if (residual) PetscValidRealPointer(residual, 5); 17795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) snes, &comm)); 17805f80ce2aSJacob Faibussowitsch CHKERRQ(DMComputeExactSolution(dm, 0.0, u, NULL)); 17815f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &r)); 17825f80ce2aSJacob Faibussowitsch CHKERRQ(SNESComputeFunction(snes, u, r)); 17835f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(r, NORM_2, &res)); 1784f017bcb6SMatthew G. Knepley if (tol >= 0.0) { 17852c71b3e2SJacob Faibussowitsch PetscCheckFalse(res > tol,comm, PETSC_ERR_ARG_WRONG, "L_2 Residual %g exceeds tolerance %g", (double) res, (double) tol); 1786b878532fSMatthew G. Knepley } else if (residual) { 1787b878532fSMatthew G. Knepley *residual = res; 1788f017bcb6SMatthew G. Knepley } else { 17895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(comm, "L_2 Residual: %g\n", (double)res)); 17905f80ce2aSJacob Faibussowitsch CHKERRQ(VecChop(r, 1.0e-10)); 17915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) r, "Initial Residual")); 17925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)r,"res_")); 17935f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(r, NULL, "-vec_view")); 1794f017bcb6SMatthew G. Knepley } 17955f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&r)); 1796f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1797f017bcb6SMatthew G. Knepley } 1798f017bcb6SMatthew G. Knepley 1799f017bcb6SMatthew G. Knepley /*@C 1800f3c94560SMatthew G. Knepley DMSNESCheckJacobian - Check the Jacobian of the exact solution against the residual using the Taylor Test 1801f017bcb6SMatthew G. Knepley 1802f017bcb6SMatthew G. Knepley Input Parameters: 1803f017bcb6SMatthew G. Knepley + snes - the SNES object 1804f017bcb6SMatthew G. Knepley . dm - the DM 1805f017bcb6SMatthew G. Knepley . u - a DM vector 1806f0fc11ceSJed Brown - tol - A tolerance for the check, or -1 to print the results instead 1807f017bcb6SMatthew G. Knepley 1808f3c94560SMatthew G. Knepley Output Parameters: 1809f3c94560SMatthew G. Knepley + isLinear - Flag indicaing that the function looks linear, or NULL 1810f3c94560SMatthew G. Knepley - convRate - The rate of convergence of the linear model, or NULL 1811f3c94560SMatthew G. Knepley 1812f017bcb6SMatthew G. Knepley Level: developer 1813f017bcb6SMatthew G. Knepley 1814f017bcb6SMatthew G. Knepley .seealso: DNSNESCheckFromOptions(), DMSNESCheckDiscretization(), DMSNESCheckResidual() 1815f017bcb6SMatthew G. Knepley @*/ 1816f3c94560SMatthew G. Knepley PetscErrorCode DMSNESCheckJacobian(SNES snes, DM dm, Vec u, PetscReal tol, PetscBool *isLinear, PetscReal *convRate) 1817f017bcb6SMatthew G. Knepley { 1818f017bcb6SMatthew G. Knepley MPI_Comm comm; 1819f017bcb6SMatthew G. Knepley PetscDS ds; 1820f017bcb6SMatthew G. Knepley Mat J, M; 1821f017bcb6SMatthew G. Knepley MatNullSpace nullspace; 1822f3c94560SMatthew G. Knepley PetscReal slope, intercept; 18237f96f943SMatthew G. Knepley PetscBool hasJac, hasPrec, isLin = PETSC_FALSE; 1824f017bcb6SMatthew G. Knepley 1825f017bcb6SMatthew G. Knepley PetscFunctionBegin; 1826f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 1827f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1828f3c94560SMatthew G. Knepley PetscValidHeaderSpecific(u, VEC_CLASSID, 3); 1829534a8f05SLisandro Dalcin if (isLinear) PetscValidBoolPointer(isLinear, 5); 1830064a246eSJacob Faibussowitsch if (convRate) PetscValidRealPointer(convRate, 6); 18315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject) snes, &comm)); 18325f80ce2aSJacob Faibussowitsch CHKERRQ(DMComputeExactSolution(dm, 0.0, u, NULL)); 1833f017bcb6SMatthew G. Knepley /* Create and view matrices */ 18345f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMatrix(dm, &J)); 18355f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm, &ds)); 18365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSHasJacobian(ds, &hasJac)); 18375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSHasJacobianPreconditioner(ds, &hasPrec)); 1838282e7bb4SMatthew G. Knepley if (hasJac && hasPrec) { 18395f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMatrix(dm, &M)); 18405f80ce2aSJacob Faibussowitsch CHKERRQ(SNESComputeJacobian(snes, u, J, M)); 18415f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) M, "Preconditioning Matrix")); 18425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) M, "jacpre_")); 18435f80ce2aSJacob Faibussowitsch CHKERRQ(MatViewFromOptions(M, NULL, "-mat_view")); 18445f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&M)); 1845282e7bb4SMatthew G. Knepley } else { 18465f80ce2aSJacob Faibussowitsch CHKERRQ(SNESComputeJacobian(snes, u, J, J)); 1847282e7bb4SMatthew G. Knepley } 18485f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject) J, "Jacobian")); 18495f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) J, "jac_")); 18505f80ce2aSJacob Faibussowitsch CHKERRQ(MatViewFromOptions(J, NULL, "-mat_view")); 1851f017bcb6SMatthew G. Knepley /* Check nullspace */ 18525f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNullSpace(J, &nullspace)); 1853f017bcb6SMatthew G. Knepley if (nullspace) { 18541878804aSMatthew G. Knepley PetscBool isNull; 18555f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceTest(nullspace, J, &isNull)); 1856*28b400f6SJacob Faibussowitsch PetscCheck(isNull,comm, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid."); 18571878804aSMatthew G. Knepley } 1858f017bcb6SMatthew G. Knepley /* Taylor test */ 1859f017bcb6SMatthew G. Knepley { 1860f017bcb6SMatthew G. Knepley PetscRandom rand; 1861f017bcb6SMatthew G. Knepley Vec du, uhat, r, rhat, df; 1862f3c94560SMatthew G. Knepley PetscReal h; 1863f017bcb6SMatthew G. Knepley PetscReal *es, *hs, *errors; 1864f017bcb6SMatthew G. Knepley PetscReal hMax = 1.0, hMin = 1e-6, hMult = 0.1; 1865f017bcb6SMatthew G. Knepley PetscInt Nv, v; 1866f017bcb6SMatthew G. Knepley 1867f017bcb6SMatthew G. Knepley /* Choose a perturbation direction */ 18685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomCreate(comm, &rand)); 18695f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &du)); 18705f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetRandom(du, rand)); 18715f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomDestroy(&rand)); 18725f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &df)); 18735f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(J, du, df)); 1874f017bcb6SMatthew G. Knepley /* Evaluate residual at u, F(u), save in vector r */ 18755f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &r)); 18765f80ce2aSJacob Faibussowitsch CHKERRQ(SNESComputeFunction(snes, u, r)); 1877f017bcb6SMatthew G. Knepley /* Look at the convergence of our Taylor approximation as we approach u */ 1878f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv); 18795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc3(Nv, &es, Nv, &hs, Nv, &errors)); 18805f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &uhat)); 18815f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &rhat)); 1882f017bcb6SMatthew G. Knepley for (h = hMax, Nv = 0; h >= hMin; h *= hMult, ++Nv) { 18835f80ce2aSJacob Faibussowitsch CHKERRQ(VecWAXPY(uhat, h, du, u)); 1884f017bcb6SMatthew G. Knepley /* F(\hat u) \approx F(u) + J(u) (uhat - u) = F(u) + h * J(u) du */ 18855f80ce2aSJacob Faibussowitsch CHKERRQ(SNESComputeFunction(snes, uhat, rhat)); 18865f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPBYPCZ(rhat, -1.0, -h, 1.0, r, df)); 18875f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(rhat, NORM_2, &errors[Nv])); 1888f017bcb6SMatthew G. Knepley 1889f017bcb6SMatthew G. Knepley es[Nv] = PetscLog10Real(errors[Nv]); 1890f017bcb6SMatthew G. Knepley hs[Nv] = PetscLog10Real(h); 1891f017bcb6SMatthew G. Knepley } 18925f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&uhat)); 18935f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&rhat)); 18945f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&df)); 18955f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&r)); 18965f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&du)); 1897f017bcb6SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 1898f017bcb6SMatthew G. Knepley if ((tol >= 0) && (errors[v] > tol)) break; 1899f017bcb6SMatthew G. Knepley else if (errors[v] > PETSC_SMALL) break; 1900f017bcb6SMatthew G. Knepley } 1901f3c94560SMatthew G. Knepley if (v == Nv) isLin = PETSC_TRUE; 19025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLinearRegression(Nv, hs, es, &slope, &intercept)); 19035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(es, hs, errors)); 1904f017bcb6SMatthew G. Knepley /* Slope should be about 2 */ 1905f017bcb6SMatthew G. Knepley if (tol >= 0) { 19062c71b3e2SJacob Faibussowitsch PetscCheckFalse(!isLin && PetscAbsReal(2 - slope) > tol,comm, PETSC_ERR_ARG_WRONG, "Taylor approximation convergence rate should be 2, not %0.2f", (double) slope); 1907b878532fSMatthew G. Knepley } else if (isLinear || convRate) { 1908b878532fSMatthew G. Knepley if (isLinear) *isLinear = isLin; 1909b878532fSMatthew G. Knepley if (convRate) *convRate = slope; 1910f017bcb6SMatthew G. Knepley } else { 19115f80ce2aSJacob Faibussowitsch if (!isLin) CHKERRQ(PetscPrintf(comm, "Taylor approximation converging at order %3.2f\n", (double) slope)); 19125f80ce2aSJacob Faibussowitsch else CHKERRQ(PetscPrintf(comm, "Function appears to be linear\n")); 1913f017bcb6SMatthew G. Knepley } 1914f017bcb6SMatthew G. Knepley } 19155f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&J)); 19161878804aSMatthew G. Knepley PetscFunctionReturn(0); 19171878804aSMatthew G. Knepley } 19181878804aSMatthew G. Knepley 19197f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheck_Internal(SNES snes, DM dm, Vec u) 1920f017bcb6SMatthew G. Knepley { 1921f017bcb6SMatthew G. Knepley PetscFunctionBegin; 19225f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESCheckDiscretization(snes, dm, 0.0, u, -1.0, NULL)); 19235f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESCheckResidual(snes, dm, u, -1.0, NULL)); 19245f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESCheckJacobian(snes, dm, u, -1.0, NULL, NULL)); 1925f017bcb6SMatthew G. Knepley PetscFunctionReturn(0); 1926f017bcb6SMatthew G. Knepley } 1927f017bcb6SMatthew G. Knepley 1928bee9a294SMatthew G. Knepley /*@C 1929bee9a294SMatthew G. Knepley DMSNESCheckFromOptions - Check the residual and Jacobian functions using the exact solution by outputting some diagnostic information 1930bee9a294SMatthew G. Knepley 1931bee9a294SMatthew G. Knepley Input Parameters: 1932bee9a294SMatthew G. Knepley + snes - the SNES object 19337f96f943SMatthew G. Knepley - u - representative SNES vector 19347f96f943SMatthew G. Knepley 19357f96f943SMatthew G. Knepley Note: The user must call PetscDSSetExactSolution() beforehand 1936bee9a294SMatthew G. Knepley 1937bee9a294SMatthew G. Knepley Level: developer 1938bee9a294SMatthew G. Knepley @*/ 19397f96f943SMatthew G. Knepley PetscErrorCode DMSNESCheckFromOptions(SNES snes, Vec u) 19401878804aSMatthew G. Knepley { 19411878804aSMatthew G. Knepley DM dm; 19421878804aSMatthew G. Knepley Vec sol; 19431878804aSMatthew G. Knepley PetscBool check; 19441878804aSMatthew G. Knepley 19451878804aSMatthew G. Knepley PetscFunctionBegin; 19465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHasName(((PetscObject)snes)->options,((PetscObject)snes)->prefix, "-dmsnes_check", &check)); 19471878804aSMatthew G. Knepley if (!check) PetscFunctionReturn(0); 19485f80ce2aSJacob Faibussowitsch CHKERRQ(SNESGetDM(snes, &dm)); 19495f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &sol)); 19505f80ce2aSJacob Faibussowitsch CHKERRQ(SNESSetSolution(snes, sol)); 19515f80ce2aSJacob Faibussowitsch CHKERRQ(DMSNESCheck_Internal(snes, dm, sol)); 19525f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&sol)); 1953552f7358SJed Brown PetscFunctionReturn(0); 1954552f7358SJed Brown } 1955