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 **/ 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 **/ 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 **/ 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 **/ 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 **/ 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 **/ 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 Honee honee; 2225e79d562SJames Wright Ceed ceed; 2235e79d562SJames Wright DM dm, dm_coord; 2245e79d562SJames Wright HoneeBCStruct honee_bc; 2255e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q; 2261abc2837SJames Wright CeedInt q_data_size, num_comps_jac_data; 2275e79d562SJames Wright CeedVector q_data, jac_data; 2285e79d562SJames Wright CeedOperator sub_op_ifunc_; 2295e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac; 2305e79d562SJames Wright CeedBasis basis_x, basis_q; 2315e79d562SJames Wright 2325e79d562SJames Wright PetscFunctionBeginUser; 2335e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 2345e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 2355e79d562SJames Wright honee = honee_bc->honee; 2365e79d562SJames Wright ceed = honee_bc->honee->ceed; 2371abc2837SJames Wright num_comps_jac_data = honee_bc->num_comps_jac_data; 2385e79d562SJames Wright 2395e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 2405e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size)); 2415e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 2425e79d562SJames Wright 2435e79d562SJames Wright { 2445e79d562SJames Wright PetscSection section; 2455e79d562SJames Wright 2465e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 2475e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 2485e79d562SJames Wright } 2495e79d562SJames Wright 2505e79d562SJames Wright PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 2515e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &basis_q)); 2525e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm_coord, domain_label, label_value, height, bc_def->dm_field, &basis_x)); 2535e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionCreate(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &elem_restr_q)); 2545e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionCoordinateCreate(ceed, dm, domain_label, label_value, height, &elem_restr_x)); 2551abc2837SJames Wright if (num_comps_jac_data > 0) { 2561abc2837SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, num_comps_jac_data, &elem_restr_jac)); 2575e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_jac, &jac_data, NULL)); 2585e79d562SJames Wright } 2595e79d562SJames Wright 2605e79d562SJames Wright PetscCall(QDataBoundaryGet(ceed, dm, domain_label, label_value, elem_restr_x, basis_x, honee->x_coord, &elem_restr_qd, &q_data, &q_data_size)); 2615e79d562SJames Wright 2625e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_ifunc, NULL, NULL, &sub_op_ifunc_)); 2635e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 2645e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "Grad_q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 2655e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface qdata", elem_restr_qd, CEED_BASIS_NONE, q_data)); 2665e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "x", elem_restr_x, basis_x, honee->x_coord)); 2675e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "v", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 2681abc2837SJames Wright if (num_comps_jac_data > 0) 2691abc2837SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface jacobian data", elem_restr_jac, CEED_BASIS_NONE, jac_data)); 2705e79d562SJames Wright 271*da7f3a07SJames Wright PetscCallCeed(ceed, CeedOperatorCompositeAddSub(op_ifunc, sub_op_ifunc_)); 2725e79d562SJames Wright *sub_op_ifunc = sub_op_ifunc_; 2735e79d562SJames Wright 2745e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 2755e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 2765e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x)); 2775e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 2785e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 2795e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x)); 2801abc2837SJames Wright if (num_comps_jac_data > 0) { 2815e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac)); 2825e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data)); 2835e79d562SJames Wright } 2845e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2855e79d562SJames Wright } 2865e79d562SJames Wright 2875e79d562SJames Wright /** 2885e79d562SJames Wright @brief Setups and adds IJacobian operator to given composite operator 2895e79d562SJames Wright 2905e79d562SJames Wright The field data (element restriction, vector, etc) is read from `sub_op_ifunc` and used for the IJacobian. 2915e79d562SJames Wright 2925e79d562SJames Wright @param[in] bc_def `BCDefinition` for the boundary condition IJacobian 2935e79d562SJames Wright @param[out] sub_op_ifunc IFunction operator corresponding to this IJacobian operator. 2945e79d562SJames Wright @param[in] domain_label `DMLabel` for the face orientation label 2955e79d562SJames Wright @param[in] label_value Orientation value 2965e79d562SJames Wright @param[in] qf_ijac QFunction for the IJacobian 2975e79d562SJames Wright @param[in,out] op_ijac Composite operator to be added to 2985e79d562SJames Wright **/ 2995e79d562SJames Wright PetscErrorCode HoneeBCAddIJacobianOp(BCDefinition bc_def, CeedOperator sub_op_ifunc, DMLabel domain_label, PetscInt label_value, 3005e79d562SJames Wright CeedQFunction qf_ijac, CeedOperator op_ijac) { 3015e79d562SJames Wright Honee honee; 3025e79d562SJames Wright Ceed ceed; 3035e79d562SJames Wright DM dm, dm_coord; 3045e79d562SJames Wright HoneeBCStruct honee_bc; 3055e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q; 3065e79d562SJames Wright CeedInt q_data_size; 3075e79d562SJames Wright CeedVector q_data, jac_data; 3085e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac; 3095e79d562SJames Wright CeedOperator sub_op_ijac; 3105e79d562SJames Wright CeedBasis basis_x, basis_q; 3115e79d562SJames Wright 3125e79d562SJames Wright PetscFunctionBeginUser; 3135e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 3141abc2837SJames Wright PetscBool use_jac_data = honee_bc->num_comps_jac_data > 0; 3155e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 3165e79d562SJames Wright honee = honee_bc->honee; 3175e79d562SJames Wright ceed = honee_bc->honee->ceed; 3185e79d562SJames Wright 3195e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 3205e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size)); 3215e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 3225e79d562SJames Wright 3235e79d562SJames Wright { 3245e79d562SJames Wright PetscSection section; 3255e79d562SJames Wright 3265e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 3275e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 3285e79d562SJames Wright } 3295e79d562SJames Wright 3305e79d562SJames Wright PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 3315e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &basis_q)); 3325e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm_coord, domain_label, label_value, height, bc_def->dm_field, &basis_x)); 3335e79d562SJames Wright 3345e79d562SJames Wright { // Get restriction and basis from the RHS function 3355e79d562SJames Wright CeedOperatorField op_field; 3365e79d562SJames Wright 3375e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "q", &op_field)); 3385e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetElemRestriction(op_field, &elem_restr_q)); 3395e79d562SJames Wright 3405e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "x", &op_field)); 3415e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetElemRestriction(op_field, &elem_restr_x)); 3425e79d562SJames Wright 343ea091b8eSJames Wright if (use_jac_data) { 3445e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "surface jacobian data", &op_field)); 3455e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_jac, NULL, &jac_data)); 3465e79d562SJames Wright } 347ea091b8eSJames Wright } 3485e79d562SJames Wright 3495e79d562SJames Wright PetscCall(QDataBoundaryGet(ceed, dm, domain_label, label_value, elem_restr_x, basis_x, honee->x_coord, &elem_restr_qd, &q_data, &q_data_size)); 3505e79d562SJames Wright 3515e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_ijac, NULL, NULL, &sub_op_ijac)); 3525e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "dq", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 3535e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "Grad_dq", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 3545e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "surface qdata", elem_restr_qd, CEED_BASIS_NONE, q_data)); 3555e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "x", elem_restr_x, basis_x, honee->x_coord)); 356ea091b8eSJames Wright if (use_jac_data) PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "surface jacobian data", elem_restr_jac, CEED_BASIS_NONE, jac_data)); 3575e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "v", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 3585e79d562SJames Wright 359*da7f3a07SJames Wright PetscCallCeed(ceed, CeedOperatorCompositeAddSub(op_ijac, sub_op_ijac)); 3605e79d562SJames Wright 3615e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 3625e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x)); 363ea091b8eSJames Wright if (use_jac_data) { 3645e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac)); 3655e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data)); 366ea091b8eSJames Wright } 3675e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 3685e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 3695e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 3705e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x)); 3715e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ijac)); 3725e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 3735e79d562SJames Wright } 374