1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors.
2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause
3487a3b6eSJames Wright
4149fb536SJames Wright #include <navierstokes.h>
55e79d562SJames Wright #include "petscerror.h"
6487a3b6eSJames Wright
7487a3b6eSJames Wright /**
8487a3b6eSJames Wright @brief Add `BCDefinition` to a `PetscSegBuffer`
9487a3b6eSJames Wright
10487a3b6eSJames Wright @param[in] bc_def `BCDefinition` to add
11487a3b6eSJames Wright @param[in,out] bc_defs_seg `PetscSegBuffer` to add to
12487a3b6eSJames Wright **/
AddBCDefinitionToSegBuffer(BCDefinition bc_def,PetscSegBuffer bc_defs_seg)13487a3b6eSJames Wright static PetscErrorCode AddBCDefinitionToSegBuffer(BCDefinition bc_def, PetscSegBuffer bc_defs_seg) {
14487a3b6eSJames Wright BCDefinition *bc_def_ptr;
15487a3b6eSJames Wright
16487a3b6eSJames Wright PetscFunctionBeginUser;
17487a3b6eSJames Wright if (bc_def == NULL) PetscFunctionReturn(PETSC_SUCCESS);
18487a3b6eSJames Wright PetscCall(PetscSegBufferGet(bc_defs_seg, 1, &bc_def_ptr));
19487a3b6eSJames Wright *bc_def_ptr = bc_def;
20487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS);
21487a3b6eSJames Wright }
22487a3b6eSJames Wright
23487a3b6eSJames Wright /**
24d3c60affSJames Wright @brief Create and setup `BCDefinition`s from commandline options
25487a3b6eSJames Wright
260c373b74SJames Wright @param[in] honee `Honee`
27487a3b6eSJames Wright @param[in,out] problem `ProblemData`
28487a3b6eSJames Wright @param[in] app_ctx `AppCtx`
29487a3b6eSJames Wright **/
BoundaryConditionSetUp(Honee honee,ProblemData problem,AppCtx app_ctx)30d3c60affSJames Wright PetscErrorCode BoundaryConditionSetUp(Honee honee, ProblemData problem, AppCtx app_ctx) {
31487a3b6eSJames Wright PetscSegBuffer bc_defs_seg;
32487a3b6eSJames Wright PetscBool flg;
33487a3b6eSJames Wright BCDefinition bc_def;
34487a3b6eSJames Wright
35487a3b6eSJames Wright PetscFunctionBeginUser;
36487a3b6eSJames Wright PetscCall(PetscSegBufferCreate(sizeof(BCDefinition), 4, &bc_defs_seg));
37487a3b6eSJames Wright
380c373b74SJames Wright PetscOptionsBegin(honee->comm, NULL, "Boundary Condition Options", NULL);
39487a3b6eSJames Wright
40487a3b6eSJames Wright PetscCall(PetscOptionsBCDefinition("-bc_wall", "Face IDs to apply wall BC", NULL, "wall", &bc_def, NULL));
41487a3b6eSJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg));
42487a3b6eSJames Wright if (bc_def) {
43487a3b6eSJames Wright PetscInt num_essential_comps = 16, essential_comps[16];
44487a3b6eSJames Wright
45487a3b6eSJames Wright PetscCall(PetscOptionsIntArray("-wall_comps", "An array of constrained component numbers", NULL, essential_comps, &num_essential_comps, &flg));
46487a3b6eSJames Wright PetscCall(BCDefinitionSetEssential(bc_def, num_essential_comps, essential_comps));
47487a3b6eSJames Wright
48487a3b6eSJames Wright app_ctx->wall_forces.num_wall = bc_def->num_label_values;
49487a3b6eSJames Wright PetscCall(PetscMalloc1(bc_def->num_label_values, &app_ctx->wall_forces.walls));
50487a3b6eSJames Wright PetscCall(PetscArraycpy(app_ctx->wall_forces.walls, bc_def->label_values, bc_def->num_label_values));
51487a3b6eSJames Wright }
52487a3b6eSJames Wright
53487a3b6eSJames Wright { // Symmetry Boundary Conditions
54487a3b6eSJames Wright const char *deprecated[3] = {"-bc_slip_x", "-bc_slip_y", "-bc_slip_z"};
55487a3b6eSJames Wright const char *flags[3] = {"-bc_symmetry_x", "-bc_symmetry_y", "-bc_symmetry_z"};
56487a3b6eSJames Wright
57487a3b6eSJames Wright for (PetscInt j = 0; j < 3; j++) {
58487a3b6eSJames Wright PetscCall(PetscOptionsDeprecated(deprecated[j], flags[j], "libCEED 0.12.0",
59487a3b6eSJames Wright "Use -bc_symmetry_[x,y,z] for direct equivalency, or -bc_slip for weak, Riemann-based, direction-invariant "
60487a3b6eSJames Wright "slip/no-penatration boundary conditions"));
61487a3b6eSJames Wright PetscCall(PetscOptionsBCDefinition(flags[j], "Face IDs to apply symmetry BC", NULL, "symmetry", &bc_def, NULL));
62487a3b6eSJames Wright if (!bc_def) {
63487a3b6eSJames Wright PetscCall(PetscOptionsBCDefinition(deprecated[j], "Face IDs to apply symmetry BC", NULL, "symmetry", &bc_def, NULL));
64487a3b6eSJames Wright }
65487a3b6eSJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg));
66487a3b6eSJames Wright if (bc_def) {
67487a3b6eSJames Wright PetscInt essential_comps[1] = {j + 1};
68487a3b6eSJames Wright
69487a3b6eSJames Wright PetscCall(BCDefinitionSetEssential(bc_def, 1, essential_comps));
70487a3b6eSJames Wright }
71487a3b6eSJames Wright }
72487a3b6eSJames Wright }
73487a3b6eSJames Wright
74d6cac220SJames Wright PetscCall(PetscOptionsBCDefinition("-bc_inflow", "Face IDs to apply inflow BC", NULL, "inflow", &bc_def, NULL));
75d6cac220SJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg));
76f978755dSJames Wright
77f978755dSJames Wright PetscCall(PetscOptionsBCDefinition("-bc_outflow", "Face IDs to apply outflow BC", NULL, "outflow", &bc_def, NULL));
78f978755dSJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg));
79d4e423e7SJames Wright
80d4e423e7SJames Wright PetscCall(PetscOptionsBCDefinition("-bc_freestream", "Face IDs to apply freestream BC", NULL, "freestream", &bc_def, NULL));
81d4e423e7SJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg));
82487a3b6eSJames Wright
835e79d562SJames Wright PetscCall(PetscOptionsBCDefinition("-bc_slip", "Face IDs to apply slip BC", NULL, "slip", &bc_def, NULL));
845e79d562SJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg));
85487a3b6eSJames Wright
86487a3b6eSJames Wright PetscOptionsEnd();
87487a3b6eSJames Wright
88487a3b6eSJames Wright PetscCall(PetscSegBufferGetSize(bc_defs_seg, &problem->num_bc_defs));
89487a3b6eSJames Wright PetscCall(PetscSegBufferExtractAlloc(bc_defs_seg, &problem->bc_defs));
90487a3b6eSJames Wright PetscCall(PetscSegBufferDestroy(&bc_defs_seg));
91487a3b6eSJames Wright
92487a3b6eSJames Wright //TODO: Verify that the BCDefinition don't have overlapping claims to boundary faces
93487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS);
94487a3b6eSJames Wright }
955e79d562SJames Wright
965e79d562SJames Wright /**
975e79d562SJames Wright @brief Destroy `HoneeBCStruct` object
985e79d562SJames Wright
995e79d562SJames Wright @param[in] ctx Pointer to `HoneeBCStruct`
1005e79d562SJames Wright **/
HoneeBCDestroy(void ** ctx)1015e79d562SJames Wright PetscErrorCode HoneeBCDestroy(void **ctx) {
1025e79d562SJames Wright HoneeBCStruct honee_bc = *(HoneeBCStruct *)ctx;
1035e79d562SJames Wright Ceed ceed = honee_bc->honee->ceed;
1045e79d562SJames Wright
1055e79d562SJames Wright PetscFunctionBeginUser;
1065e79d562SJames Wright if (honee_bc->qfctx) PetscCallCeed(ceed, CeedQFunctionContextDestroy(&honee_bc->qfctx));
10714bd2a07SJames Wright if (honee_bc->DestroyCtx) PetscCall((*honee_bc->DestroyCtx)(&honee_bc->ctx));
1085e79d562SJames Wright PetscCall(PetscFree(honee_bc));
1095e79d562SJames Wright *ctx = NULL;
1105e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
1115e79d562SJames Wright }
1125e79d562SJames Wright
1135e79d562SJames Wright /**
1145e79d562SJames Wright @brief Create a QFunction matching the "standard" HONEE inputs for IFunctions
1155e79d562SJames Wright
1165e79d562SJames Wright This assumes the `bc_def` context is a `HoneeBCStruct` and inputs/outputs of the IFunction QFunction are in the correct order.
1175e79d562SJames Wright
1185e79d562SJames Wright @param[in] bc_def `BCDefinition` that hosts the IFunction
1195e79d562SJames Wright @param[in] qf_func_ptr `CeedQFunctionUser` for the IFunction
1205e79d562SJames Wright @param[in] qf_loc Absolute path to source of `CeedQFunctionUser`
1215e79d562SJames Wright @param[in] qfctx `CeedQFunctionContext` for the IFunction (also shared with the IJacobian, if applicable)
1225e79d562SJames Wright @param[out] qf_ifunc QFunction for the IFunction
1235e79d562SJames Wright **/
HoneeBCCreateIFunctionQF(BCDefinition bc_def,CeedQFunctionUser qf_func_ptr,const char * qf_loc,CeedQFunctionContext qfctx,CeedQFunction * qf_ifunc)1245e79d562SJames Wright PetscErrorCode HoneeBCCreateIFunctionQF(BCDefinition bc_def, CeedQFunctionUser qf_func_ptr, const char *qf_loc, CeedQFunctionContext qfctx,
1255e79d562SJames Wright CeedQFunction *qf_ifunc) {
1265e79d562SJames Wright Ceed ceed;
1275e79d562SJames Wright DM dm;
1285e79d562SJames Wright PetscInt dim, dim_sur, height = 1, num_comp_x, num_comp_q;
1291abc2837SJames Wright CeedInt q_data_size_sur, num_comps_jac_data;
1305e79d562SJames Wright HoneeBCStruct honee_bc;
1315e79d562SJames Wright
1325e79d562SJames Wright PetscFunctionBeginUser;
1335e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm));
1345e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc));
1355e79d562SJames Wright ceed = honee_bc->honee->ceed;
1361abc2837SJames Wright num_comps_jac_data = honee_bc->num_comps_jac_data;
1375e79d562SJames Wright
1385e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim));
1395e79d562SJames Wright dim_sur = dim - height;
1405e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size_sur));
1415e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x));
1425e79d562SJames Wright {
1435e79d562SJames Wright PetscSection section;
1445e79d562SJames Wright
1455e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion));
1465e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q));
1475e79d562SJames Wright }
1485e79d562SJames Wright
1495e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, qf_func_ptr, qf_loc, qf_ifunc));
1505e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(*qf_ifunc, qfctx));
1515e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(*qf_ifunc, 0));
1525e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "q", num_comp_q, CEED_EVAL_INTERP));
1535e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "Grad_q", num_comp_q * dim_sur, CEED_EVAL_GRAD));
1545e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "surface qdata", q_data_size_sur, CEED_EVAL_NONE));
1555e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "x", num_comp_x, CEED_EVAL_INTERP));
1565e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ifunc, "v", num_comp_q, CEED_EVAL_INTERP));
1571abc2837SJames Wright if (num_comps_jac_data) PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ifunc, "surface jacobian data", num_comps_jac_data, CEED_EVAL_NONE));
1585e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
1595e79d562SJames Wright }
1605e79d562SJames Wright
1615e79d562SJames Wright /**
1625e79d562SJames Wright @brief Create a QFunction matching the "standard" HONEE inputs for IJacobian
1635e79d562SJames Wright
1645e79d562SJames Wright This assumes the `bc_def` context is a `HoneeBCStruct` and inputs/outputs of the IJacobian QFunction are in the correct order.
1655e79d562SJames Wright
1665e79d562SJames Wright @param[in] bc_def `BCDefinition` that hosts the IJacobian
1675e79d562SJames Wright @param[in] qf_func_ptr `CeedQFunctionUser` for the IJacobian
1685e79d562SJames Wright @param[in] qf_loc Absolute path to source of `CeedQFunctionUser`
1695e79d562SJames Wright @param[in] qfctx `CeedQFunctionContext` for the IJacobian (also shared with the IFunction)
1705e79d562SJames Wright @param[out] qf_ijac QFunction for the IJacobian
1715e79d562SJames Wright **/
HoneeBCCreateIJacobianQF(BCDefinition bc_def,CeedQFunctionUser qf_func_ptr,const char * qf_loc,CeedQFunctionContext qfctx,CeedQFunction * qf_ijac)1725e79d562SJames Wright PetscErrorCode HoneeBCCreateIJacobianQF(BCDefinition bc_def, CeedQFunctionUser qf_func_ptr, const char *qf_loc, CeedQFunctionContext qfctx,
1735e79d562SJames Wright CeedQFunction *qf_ijac) {
1745e79d562SJames Wright Ceed ceed;
1755e79d562SJames Wright DM dm;
1765e79d562SJames Wright PetscInt dim, dim_sur, height = 1, num_comp_x, num_comp_q;
1771abc2837SJames Wright CeedInt q_data_size_sur, num_comps_jac_data;
1785e79d562SJames Wright HoneeBCStruct honee_bc;
1795e79d562SJames Wright
1805e79d562SJames Wright PetscFunctionBeginUser;
1815e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm));
1825e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc));
1835e79d562SJames Wright ceed = honee_bc->honee->ceed;
1841abc2837SJames Wright num_comps_jac_data = honee_bc->num_comps_jac_data;
1855e79d562SJames Wright
1865e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim));
1875e79d562SJames Wright dim_sur = dim - height;
1885e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size_sur));
1895e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x));
1905e79d562SJames Wright {
1915e79d562SJames Wright PetscSection section;
1925e79d562SJames Wright
1935e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion));
1945e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q));
1955e79d562SJames Wright }
1965e79d562SJames Wright
1975e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, qf_func_ptr, qf_loc, qf_ijac));
1985e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(*qf_ijac, qfctx));
1995e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(*qf_ijac, 0));
2005e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "dq", num_comp_q, CEED_EVAL_INTERP));
2015e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "Grad_dq", num_comp_q * dim_sur, CEED_EVAL_GRAD));
2025e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "surface qdata", q_data_size_sur, CEED_EVAL_NONE));
2035e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "x", num_comp_x, CEED_EVAL_INTERP));
2041abc2837SJames Wright if (num_comps_jac_data) PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "surface jacobian data", num_comps_jac_data, CEED_EVAL_NONE));
2055e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ijac, "v", num_comp_q, CEED_EVAL_INTERP));
2065e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
2075e79d562SJames Wright }
2085e79d562SJames Wright
2095e79d562SJames Wright /**
2105e79d562SJames Wright @brief Setups and adds IFunction operator to given composite operator
2115e79d562SJames Wright
2125e79d562SJames Wright @param[in] bc_def `BCDefinition` for the boundary condition IFunction
2135e79d562SJames Wright @param[in] domain_label `DMLabel` for the face orientation label
2145e79d562SJames Wright @param[in] label_value Orientation value
2155e79d562SJames Wright @param[in] qf_ifunc QFunction for the IFunction
2165e79d562SJames Wright @param[in,out] op_ifunc Composite operator to be added to
2175e79d562SJames Wright @param[out] sub_op_ifunc Non-composite operator that is added in this function. To be passed to `HoneeBCAddIJacobianOp()`
2185e79d562SJames Wright **/
HoneeBCAddIFunctionOp(BCDefinition bc_def,DMLabel domain_label,PetscInt label_value,CeedQFunction qf_ifunc,CeedOperator op_ifunc,CeedOperator * sub_op_ifunc)2195e79d562SJames Wright PetscErrorCode HoneeBCAddIFunctionOp(BCDefinition bc_def, DMLabel domain_label, PetscInt label_value, CeedQFunction qf_ifunc, CeedOperator op_ifunc,
2205e79d562SJames Wright CeedOperator *sub_op_ifunc) {
2215e79d562SJames Wright Ceed ceed;
222bae0b58eSJames Wright DM dm;
2235e79d562SJames Wright HoneeBCStruct honee_bc;
2245e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q;
2251abc2837SJames Wright CeedInt q_data_size, num_comps_jac_data;
226*4fe35dceSJames Wright CeedVector q_data, jac_data, x_coord;
2275e79d562SJames Wright CeedOperator sub_op_ifunc_;
2285e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac;
2295e79d562SJames Wright CeedBasis basis_x, basis_q;
2305e79d562SJames Wright
2315e79d562SJames Wright PetscFunctionBeginUser;
2325e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm));
2335e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc));
2345e79d562SJames Wright ceed = honee_bc->honee->ceed;
2351abc2837SJames Wright num_comps_jac_data = honee_bc->num_comps_jac_data;
2365e79d562SJames Wright
2375e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim));
2385e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x));
239bae0b58eSJames Wright PetscCall(DMGetFieldNumComps(dm, bc_def->dm_field, &num_comp_q));
2405e79d562SJames Wright
2416b9fd993SJames Wright PetscCall(DMPlexCeedBasisCreate(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &basis_q));
2425e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionCreate(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &elem_restr_q));
243*4fe35dceSJames Wright PetscCall(DMPlexCeedCoordinateCreateField(ceed, dm, domain_label, label_value, height, &elem_restr_x, &basis_x, &x_coord));
24407126c9aSJames Wright PetscCall(QDataBoundaryGet(ceed, dm, domain_label, label_value, &elem_restr_qd, &q_data, &q_data_size));
2451abc2837SJames Wright if (num_comps_jac_data > 0) {
2461abc2837SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, num_comps_jac_data, &elem_restr_jac));
2475e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_jac, &jac_data, NULL));
2485e79d562SJames Wright }
2495e79d562SJames Wright
2505e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_ifunc, NULL, NULL, &sub_op_ifunc_));
2515e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
2525e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "Grad_q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
2535e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface qdata", elem_restr_qd, CEED_BASIS_NONE, q_data));
254*4fe35dceSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "x", elem_restr_x, basis_x, x_coord));
2555e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "v", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
2561abc2837SJames Wright if (num_comps_jac_data > 0)
2571abc2837SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface jacobian data", elem_restr_jac, CEED_BASIS_NONE, jac_data));
2585e79d562SJames Wright
259da7f3a07SJames Wright PetscCallCeed(ceed, CeedOperatorCompositeAddSub(op_ifunc, sub_op_ifunc_));
2605e79d562SJames Wright *sub_op_ifunc = sub_op_ifunc_;
2615e79d562SJames Wright
2625e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data));
263*4fe35dceSJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&x_coord));
2645e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q));
2655e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x));
2665e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd));
2675e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q));
2685e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x));
2691abc2837SJames Wright if (num_comps_jac_data > 0) {
2705e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac));
2715e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data));
2725e79d562SJames Wright }
2735e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
2745e79d562SJames Wright }
2755e79d562SJames Wright
2765e79d562SJames Wright /**
2775e79d562SJames Wright @brief Setups and adds IJacobian operator to given composite operator
2785e79d562SJames Wright
2795e79d562SJames Wright The field data (element restriction, vector, etc) is read from `sub_op_ifunc` and used for the IJacobian.
2805e79d562SJames Wright
2815e79d562SJames Wright @param[in] bc_def `BCDefinition` for the boundary condition IJacobian
2825e79d562SJames Wright @param[out] sub_op_ifunc IFunction operator corresponding to this IJacobian operator.
2835e79d562SJames Wright @param[in] domain_label `DMLabel` for the face orientation label
2845e79d562SJames Wright @param[in] label_value Orientation value
2855e79d562SJames Wright @param[in] qf_ijac QFunction for the IJacobian
2865e79d562SJames Wright @param[in,out] op_ijac Composite operator to be added to
2875e79d562SJames Wright **/
HoneeBCAddIJacobianOp(BCDefinition bc_def,CeedOperator sub_op_ifunc,DMLabel domain_label,PetscInt label_value,CeedQFunction qf_ijac,CeedOperator op_ijac)2885e79d562SJames Wright PetscErrorCode HoneeBCAddIJacobianOp(BCDefinition bc_def, CeedOperator sub_op_ifunc, DMLabel domain_label, PetscInt label_value,
2895e79d562SJames Wright CeedQFunction qf_ijac, CeedOperator op_ijac) {
2905e79d562SJames Wright Ceed ceed;
291bae0b58eSJames Wright DM dm;
2925e79d562SJames Wright HoneeBCStruct honee_bc;
2935e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q;
2945e79d562SJames Wright CeedInt q_data_size;
295*4fe35dceSJames Wright CeedVector q_data, jac_data, x_coord;
2965e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac;
2975e79d562SJames Wright CeedOperator sub_op_ijac;
2985e79d562SJames Wright CeedBasis basis_x, basis_q;
2995e79d562SJames Wright
3005e79d562SJames Wright PetscFunctionBeginUser;
3015e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc));
3021abc2837SJames Wright PetscBool use_jac_data = honee_bc->num_comps_jac_data > 0;
3035e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm));
3045e79d562SJames Wright ceed = honee_bc->honee->ceed;
3055e79d562SJames Wright
3065e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim));
3075e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x));
308bae0b58eSJames Wright PetscCall(DMGetFieldNumComps(dm, bc_def->dm_field, &num_comp_q));
3095e79d562SJames Wright
310*4fe35dceSJames Wright PetscCall(DMPlexCeedCoordinateCreateField(ceed, dm, domain_label, label_value, height, &elem_restr_x, &basis_x, &x_coord));
31107126c9aSJames Wright PetscCall(QDataBoundaryGet(ceed, dm, domain_label, label_value, &elem_restr_qd, &q_data, &q_data_size));
3125e79d562SJames Wright
31307126c9aSJames Wright { // Get restriction and basis from the IFunction function
3145e79d562SJames Wright CeedOperatorField op_field;
3155e79d562SJames Wright
3165e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "q", &op_field));
317*4fe35dceSJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_q, &basis_q, NULL));
318ea091b8eSJames Wright if (use_jac_data) {
3195e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "surface jacobian data", &op_field));
3205e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_jac, NULL, &jac_data));
3215e79d562SJames Wright }
322ea091b8eSJames Wright }
3235e79d562SJames Wright
3245e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_ijac, NULL, NULL, &sub_op_ijac));
3255e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "dq", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
3265e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "Grad_dq", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
3275e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "surface qdata", elem_restr_qd, CEED_BASIS_NONE, q_data));
328*4fe35dceSJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "x", elem_restr_x, basis_x, x_coord));
329ea091b8eSJames Wright if (use_jac_data) PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "surface jacobian data", elem_restr_jac, CEED_BASIS_NONE, jac_data));
3305e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "v", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE));
3315e79d562SJames Wright
332da7f3a07SJames Wright PetscCallCeed(ceed, CeedOperatorCompositeAddSub(op_ijac, sub_op_ijac));
3335e79d562SJames Wright
3345e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q));
3355e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x));
336ea091b8eSJames Wright if (use_jac_data) {
3375e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac));
3385e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data));
339ea091b8eSJames Wright }
3405e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data));
341*4fe35dceSJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&x_coord));
3425e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd));
3435e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q));
3445e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x));
3455e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ijac));
3465e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS);
3475e79d562SJames Wright }
348