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 /** 24487a3b6eSJames Wright @brief Create and setup `BCDefinition`s and `SimpleBC` 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 @param[in,out] bc `SimpleBC` 30487a3b6eSJames Wright **/ 310c373b74SJames Wright PetscErrorCode BoundaryConditionSetUp(Honee honee, ProblemData problem, AppCtx app_ctx, SimpleBC bc) { 32487a3b6eSJames Wright PetscSegBuffer bc_defs_seg; 33487a3b6eSJames Wright PetscBool flg; 34487a3b6eSJames Wright BCDefinition bc_def; 35487a3b6eSJames Wright 36487a3b6eSJames Wright PetscFunctionBeginUser; 37487a3b6eSJames Wright PetscCall(PetscSegBufferCreate(sizeof(BCDefinition), 4, &bc_defs_seg)); 38487a3b6eSJames Wright 390c373b74SJames Wright PetscOptionsBegin(honee->comm, NULL, "Boundary Condition Options", NULL); 40487a3b6eSJames Wright 41487a3b6eSJames Wright PetscCall(PetscOptionsBCDefinition("-bc_wall", "Face IDs to apply wall BC", NULL, "wall", &bc_def, NULL)); 42487a3b6eSJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg)); 43487a3b6eSJames Wright if (bc_def) { 44487a3b6eSJames Wright PetscInt num_essential_comps = 16, essential_comps[16]; 45487a3b6eSJames Wright 46487a3b6eSJames Wright PetscCall(PetscOptionsIntArray("-wall_comps", "An array of constrained component numbers", NULL, essential_comps, &num_essential_comps, &flg)); 47487a3b6eSJames Wright PetscCall(BCDefinitionSetEssential(bc_def, num_essential_comps, essential_comps)); 48487a3b6eSJames Wright 49487a3b6eSJames Wright app_ctx->wall_forces.num_wall = bc_def->num_label_values; 50487a3b6eSJames Wright PetscCall(PetscMalloc1(bc_def->num_label_values, &app_ctx->wall_forces.walls)); 51487a3b6eSJames Wright PetscCall(PetscArraycpy(app_ctx->wall_forces.walls, bc_def->label_values, bc_def->num_label_values)); 52487a3b6eSJames Wright } 53487a3b6eSJames Wright 54487a3b6eSJames Wright { // Symmetry Boundary Conditions 55487a3b6eSJames Wright const char *deprecated[3] = {"-bc_slip_x", "-bc_slip_y", "-bc_slip_z"}; 56487a3b6eSJames Wright const char *flags[3] = {"-bc_symmetry_x", "-bc_symmetry_y", "-bc_symmetry_z"}; 57487a3b6eSJames Wright 58487a3b6eSJames Wright for (PetscInt j = 0; j < 3; j++) { 59487a3b6eSJames Wright PetscCall(PetscOptionsDeprecated(deprecated[j], flags[j], "libCEED 0.12.0", 60487a3b6eSJames Wright "Use -bc_symmetry_[x,y,z] for direct equivalency, or -bc_slip for weak, Riemann-based, direction-invariant " 61487a3b6eSJames Wright "slip/no-penatration boundary conditions")); 62487a3b6eSJames Wright PetscCall(PetscOptionsBCDefinition(flags[j], "Face IDs to apply symmetry BC", NULL, "symmetry", &bc_def, NULL)); 63487a3b6eSJames Wright if (!bc_def) { 64487a3b6eSJames Wright PetscCall(PetscOptionsBCDefinition(deprecated[j], "Face IDs to apply symmetry BC", NULL, "symmetry", &bc_def, NULL)); 65487a3b6eSJames Wright } 66487a3b6eSJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg)); 67487a3b6eSJames Wright if (bc_def) { 68487a3b6eSJames Wright PetscInt essential_comps[1] = {j + 1}; 69487a3b6eSJames Wright 70487a3b6eSJames Wright PetscCall(BCDefinitionSetEssential(bc_def, 1, essential_comps)); 71487a3b6eSJames Wright } 72487a3b6eSJames Wright } 73487a3b6eSJames Wright } 74487a3b6eSJames Wright 75487a3b6eSJames Wright // Inflow BCs 76487a3b6eSJames Wright bc->num_inflow = 16; 77487a3b6eSJames Wright PetscCall(PetscOptionsIntArray("-bc_inflow", "Face IDs to apply inflow BC", NULL, bc->inflows, &bc->num_inflow, NULL)); 78*f978755dSJames Wright 79*f978755dSJames Wright PetscCall(PetscOptionsBCDefinition("-bc_outflow", "Face IDs to apply outflow BC", NULL, "outflow", &bc_def, NULL)); 80*f978755dSJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg)); 81d4e423e7SJames Wright 82d4e423e7SJames Wright PetscCall(PetscOptionsBCDefinition("-bc_freestream", "Face IDs to apply freestream BC", NULL, "freestream", &bc_def, NULL)); 83d4e423e7SJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg)); 84487a3b6eSJames Wright 855e79d562SJames Wright PetscCall(PetscOptionsBCDefinition("-bc_slip", "Face IDs to apply slip BC", NULL, "slip", &bc_def, NULL)); 865e79d562SJames Wright PetscCall(AddBCDefinitionToSegBuffer(bc_def, bc_defs_seg)); 87487a3b6eSJames Wright 88487a3b6eSJames Wright PetscOptionsEnd(); 89487a3b6eSJames Wright 90487a3b6eSJames Wright PetscCall(PetscSegBufferGetSize(bc_defs_seg, &problem->num_bc_defs)); 91487a3b6eSJames Wright PetscCall(PetscSegBufferExtractAlloc(bc_defs_seg, &problem->bc_defs)); 92487a3b6eSJames Wright PetscCall(PetscSegBufferDestroy(&bc_defs_seg)); 93487a3b6eSJames Wright 94487a3b6eSJames Wright //TODO: Verify that the BCDefinition don't have overlapping claims to boundary faces 95487a3b6eSJames Wright 96487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 97487a3b6eSJames Wright } 985e79d562SJames Wright 995e79d562SJames Wright /** 1005e79d562SJames Wright @brief Destroy `HoneeBCStruct` object 1015e79d562SJames Wright 1025e79d562SJames Wright @param[in] ctx Pointer to `HoneeBCStruct` 1035e79d562SJames Wright **/ 1045e79d562SJames Wright PetscErrorCode HoneeBCDestroy(void **ctx) { 1055e79d562SJames Wright HoneeBCStruct honee_bc = *(HoneeBCStruct *)ctx; 1065e79d562SJames Wright Ceed ceed = honee_bc->honee->ceed; 1075e79d562SJames Wright 1085e79d562SJames Wright PetscFunctionBeginUser; 1095e79d562SJames Wright if (honee_bc->qfctx) PetscCallCeed(ceed, CeedQFunctionContextDestroy(&honee_bc->qfctx)); 1105e79d562SJames Wright if (honee_bc->DestroyCtx) PetscCall((*(honee_bc->DestroyCtx))(&honee_bc->ctx)); 1115e79d562SJames Wright PetscCall(PetscFree(honee_bc)); 1125e79d562SJames Wright *ctx = NULL; 1135e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1145e79d562SJames Wright } 1155e79d562SJames Wright 1165e79d562SJames Wright /** 1175e79d562SJames Wright @brief Create a QFunction matching the "standard" HONEE inputs for IFunctions 1185e79d562SJames Wright 1195e79d562SJames Wright This assumes the `bc_def` context is a `HoneeBCStruct` and inputs/outputs of the IFunction QFunction are in the correct order. 1205e79d562SJames Wright 1215e79d562SJames Wright @param[in] bc_def `BCDefinition` that hosts the IFunction 1225e79d562SJames Wright @param[in] qf_func_ptr `CeedQFunctionUser` for the IFunction 1235e79d562SJames Wright @param[in] qf_loc Absolute path to source of `CeedQFunctionUser` 1245e79d562SJames Wright @param[in] qfctx `CeedQFunctionContext` for the IFunction (also shared with the IJacobian, if applicable) 1255e79d562SJames Wright @param[out] qf_ifunc QFunction for the IFunction 1265e79d562SJames Wright **/ 1275e79d562SJames Wright PetscErrorCode HoneeBCCreateIFunctionQF(BCDefinition bc_def, CeedQFunctionUser qf_func_ptr, const char *qf_loc, CeedQFunctionContext qfctx, 1285e79d562SJames Wright CeedQFunction *qf_ifunc) { 1295e79d562SJames Wright Ceed ceed; 1305e79d562SJames Wright DM dm; 1315e79d562SJames Wright PetscInt dim, dim_sur, height = 1, num_comp_x, num_comp_q; 1325e79d562SJames Wright CeedInt q_data_size_sur, jac_data_size_sur; 1335e79d562SJames Wright HoneeBCStruct honee_bc; 1345e79d562SJames Wright 1355e79d562SJames Wright PetscFunctionBeginUser; 1365e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 1375e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 1385e79d562SJames Wright ceed = honee_bc->honee->ceed; 1395e79d562SJames Wright jac_data_size_sur = honee_bc->jac_data_size_sur; 1405e79d562SJames Wright 1415e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 1425e79d562SJames Wright dim_sur = dim - height; 1435e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size_sur)); 1445e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 1455e79d562SJames Wright { 1465e79d562SJames Wright PetscSection section; 1475e79d562SJames Wright 1485e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 1495e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 1505e79d562SJames Wright } 1515e79d562SJames Wright 1525e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, qf_func_ptr, qf_loc, qf_ifunc)); 1535e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(*qf_ifunc, qfctx)); 1545e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(*qf_ifunc, 0)); 1555e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "q", num_comp_q, CEED_EVAL_INTERP)); 1565e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "Grad_q", num_comp_q * dim_sur, CEED_EVAL_GRAD)); 1575e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "surface qdata", q_data_size_sur, CEED_EVAL_NONE)); 1585e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "x", num_comp_x, CEED_EVAL_INTERP)); 1595e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ifunc, "v", num_comp_q, CEED_EVAL_INTERP)); 1605e79d562SJames Wright if (jac_data_size_sur) PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ifunc, "surface jacobian data", jac_data_size_sur, CEED_EVAL_NONE)); 1615e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1625e79d562SJames Wright } 1635e79d562SJames Wright 1645e79d562SJames Wright /** 1655e79d562SJames Wright @brief Create a QFunction matching the "standard" HONEE inputs for IJacobian 1665e79d562SJames Wright 1675e79d562SJames Wright This assumes the `bc_def` context is a `HoneeBCStruct` and inputs/outputs of the IJacobian QFunction are in the correct order. 1685e79d562SJames Wright 1695e79d562SJames Wright @param[in] bc_def `BCDefinition` that hosts the IJacobian 1705e79d562SJames Wright @param[in] qf_func_ptr `CeedQFunctionUser` for the IJacobian 1715e79d562SJames Wright @param[in] qf_loc Absolute path to source of `CeedQFunctionUser` 1725e79d562SJames Wright @param[in] qfctx `CeedQFunctionContext` for the IJacobian (also shared with the IFunction) 1735e79d562SJames Wright @param[out] qf_ijac QFunction for the IJacobian 1745e79d562SJames Wright **/ 1755e79d562SJames Wright PetscErrorCode HoneeBCCreateIJacobianQF(BCDefinition bc_def, CeedQFunctionUser qf_func_ptr, const char *qf_loc, CeedQFunctionContext qfctx, 1765e79d562SJames Wright CeedQFunction *qf_ijac) { 1775e79d562SJames Wright Ceed ceed; 1785e79d562SJames Wright DM dm; 1795e79d562SJames Wright PetscInt dim, dim_sur, height = 1, num_comp_x, num_comp_q; 1805e79d562SJames Wright CeedInt q_data_size_sur, jac_data_size_sur; 1815e79d562SJames Wright HoneeBCStruct honee_bc; 1825e79d562SJames Wright 1835e79d562SJames Wright PetscFunctionBeginUser; 1845e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 1855e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 1865e79d562SJames Wright ceed = honee_bc->honee->ceed; 1875e79d562SJames Wright jac_data_size_sur = honee_bc->jac_data_size_sur; 1885e79d562SJames Wright 1895e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 1905e79d562SJames Wright dim_sur = dim - height; 1915e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size_sur)); 1925e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 1935e79d562SJames Wright { 1945e79d562SJames Wright PetscSection section; 1955e79d562SJames Wright 1965e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 1975e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 1985e79d562SJames Wright } 1995e79d562SJames Wright 2005e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, qf_func_ptr, qf_loc, qf_ijac)); 2015e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(*qf_ijac, qfctx)); 2025e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(*qf_ijac, 0)); 2035e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "dq", num_comp_q, CEED_EVAL_INTERP)); 2045e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "Grad_dq", num_comp_q * dim_sur, CEED_EVAL_GRAD)); 2055e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "surface qdata", q_data_size_sur, CEED_EVAL_NONE)); 2065e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "x", num_comp_x, CEED_EVAL_INTERP)); 2075e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "surface jacobian data", jac_data_size_sur, CEED_EVAL_NONE)); 2085e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ijac, "v", num_comp_q, CEED_EVAL_INTERP)); 2095e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2105e79d562SJames Wright } 2115e79d562SJames Wright 2125e79d562SJames Wright /** 2135e79d562SJames Wright @brief Setups and adds IFunction operator to given composite operator 2145e79d562SJames Wright 2155e79d562SJames Wright @param[in] bc_def `BCDefinition` for the boundary condition IFunction 2165e79d562SJames Wright @param[in] domain_label `DMLabel` for the face orientation label 2175e79d562SJames Wright @param[in] label_value Orientation value 2185e79d562SJames Wright @param[in] qf_ifunc QFunction for the IFunction 2195e79d562SJames Wright @param[in,out] op_ifunc Composite operator to be added to 2205e79d562SJames Wright @param[out] sub_op_ifunc Non-composite operator that is added in this function. To be passed to `HoneeBCAddIJacobianOp()` 2215e79d562SJames Wright **/ 2225e79d562SJames Wright PetscErrorCode HoneeBCAddIFunctionOp(BCDefinition bc_def, DMLabel domain_label, PetscInt label_value, CeedQFunction qf_ifunc, CeedOperator op_ifunc, 2235e79d562SJames Wright CeedOperator *sub_op_ifunc) { 2245e79d562SJames Wright Honee honee; 2255e79d562SJames Wright Ceed ceed; 2265e79d562SJames Wright DM dm, dm_coord; 2275e79d562SJames Wright HoneeBCStruct honee_bc; 2285e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q; 2295e79d562SJames Wright CeedInt q_data_size, jac_data_size; 2305e79d562SJames Wright CeedVector q_data, jac_data; 2315e79d562SJames Wright CeedOperator sub_op_ifunc_; 2325e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac; 2335e79d562SJames Wright CeedBasis basis_x, basis_q; 2345e79d562SJames Wright 2355e79d562SJames Wright PetscFunctionBeginUser; 2365e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 2375e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 2385e79d562SJames Wright honee = honee_bc->honee; 2395e79d562SJames Wright ceed = honee_bc->honee->ceed; 2405e79d562SJames Wright jac_data_size = honee_bc->jac_data_size_sur; 2415e79d562SJames Wright 2425e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 2435e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size)); 2445e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 2455e79d562SJames Wright 2465e79d562SJames Wright { 2475e79d562SJames Wright PetscSection section; 2485e79d562SJames Wright 2495e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 2505e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 2515e79d562SJames Wright } 2525e79d562SJames Wright 2535e79d562SJames Wright PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 2545e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &basis_q)); 2555e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm_coord, domain_label, label_value, height, bc_def->dm_field, &basis_x)); 2565e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionCreate(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &elem_restr_q)); 2575e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionCoordinateCreate(ceed, dm, domain_label, label_value, height, &elem_restr_x)); 2585e79d562SJames Wright if (jac_data_size > 0) { 2595e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, jac_data_size, &elem_restr_jac)); 2605e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_jac, &jac_data, NULL)); 2615e79d562SJames Wright } 2625e79d562SJames Wright 2635e79d562SJames 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)); 2645e79d562SJames Wright 2655e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_ifunc, NULL, NULL, &sub_op_ifunc_)); 2665e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 2675e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "Grad_q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 2685e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface qdata", elem_restr_qd, CEED_BASIS_NONE, q_data)); 2695e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "x", elem_restr_x, basis_x, honee->x_coord)); 2705e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "v", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 2715e79d562SJames Wright if (jac_data_size > 0) PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface jacobian data", elem_restr_jac, CEED_BASIS_NONE, jac_data)); 2725e79d562SJames Wright 2735e79d562SJames Wright PetscCallCeed(ceed, CeedCompositeOperatorAddSub(op_ifunc, sub_op_ifunc_)); 2745e79d562SJames Wright *sub_op_ifunc = sub_op_ifunc_; 2755e79d562SJames Wright 2765e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 2775e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 2785e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x)); 2795e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 2805e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 2815e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x)); 2825e79d562SJames Wright if (jac_data_size > 0) { 2835e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac)); 2845e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data)); 2855e79d562SJames Wright } 2865e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2875e79d562SJames Wright } 2885e79d562SJames Wright 2895e79d562SJames Wright /** 2905e79d562SJames Wright @brief Setups and adds IJacobian operator to given composite operator 2915e79d562SJames Wright 2925e79d562SJames Wright The field data (element restriction, vector, etc) is read from `sub_op_ifunc` and used for the IJacobian. 2935e79d562SJames Wright 2945e79d562SJames Wright @param[in] bc_def `BCDefinition` for the boundary condition IJacobian 2955e79d562SJames Wright @param[out] sub_op_ifunc IFunction operator corresponding to this IJacobian operator. 2965e79d562SJames Wright @param[in] domain_label `DMLabel` for the face orientation label 2975e79d562SJames Wright @param[in] label_value Orientation value 2985e79d562SJames Wright @param[in] qf_ijac QFunction for the IJacobian 2995e79d562SJames Wright @param[in,out] op_ijac Composite operator to be added to 3005e79d562SJames Wright **/ 3015e79d562SJames Wright PetscErrorCode HoneeBCAddIJacobianOp(BCDefinition bc_def, CeedOperator sub_op_ifunc, DMLabel domain_label, PetscInt label_value, 3025e79d562SJames Wright CeedQFunction qf_ijac, CeedOperator op_ijac) { 3035e79d562SJames Wright Honee honee; 3045e79d562SJames Wright Ceed ceed; 3055e79d562SJames Wright DM dm, dm_coord; 3065e79d562SJames Wright HoneeBCStruct honee_bc; 3075e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q; 3085e79d562SJames Wright CeedInt q_data_size; 3095e79d562SJames Wright CeedVector q_data, jac_data; 3105e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac; 3115e79d562SJames Wright CeedOperator sub_op_ijac; 3125e79d562SJames Wright CeedBasis basis_x, basis_q; 3135e79d562SJames Wright 3145e79d562SJames Wright PetscFunctionBeginUser; 3155e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 3165e79d562SJames Wright if (honee_bc->jac_data_size_sur == 0) PetscFunctionReturn(PETSC_SUCCESS); 3175e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 3185e79d562SJames Wright honee = honee_bc->honee; 3195e79d562SJames Wright ceed = honee_bc->honee->ceed; 3205e79d562SJames Wright 3215e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 3225e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size)); 3235e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 3245e79d562SJames Wright 3255e79d562SJames Wright { 3265e79d562SJames Wright PetscSection section; 3275e79d562SJames Wright 3285e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 3295e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 3305e79d562SJames Wright } 3315e79d562SJames Wright 3325e79d562SJames Wright PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 3335e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &basis_q)); 3345e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm_coord, domain_label, label_value, height, bc_def->dm_field, &basis_x)); 3355e79d562SJames Wright 3365e79d562SJames Wright { // Get restriction and basis from the RHS function 3375e79d562SJames Wright CeedOperatorField op_field; 3385e79d562SJames Wright 3395e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "q", &op_field)); 3405e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetElemRestriction(op_field, &elem_restr_q)); 3415e79d562SJames Wright 3425e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "x", &op_field)); 3435e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetElemRestriction(op_field, &elem_restr_x)); 3445e79d562SJames Wright 3455e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "surface jacobian data", &op_field)); 3465e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_jac, NULL, &jac_data)); 3475e79d562SJames 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)); 3565e79d562SJames Wright 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 3595e79d562SJames Wright PetscCallCeed(ceed, CeedCompositeOperatorAddSub(op_ijac, sub_op_ijac)); 3605e79d562SJames Wright 3615e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 3625e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x)); 3635e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac)); 3645e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data)); 3655e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 3665e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 3675e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 3685e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x)); 3695e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ijac)); 3705e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 3715e79d562SJames Wright } 372