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> 5*5e79d562SJames 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)); 78487a3b6eSJames Wright // Outflow BCs 79487a3b6eSJames Wright bc->num_outflow = 16; 80487a3b6eSJames Wright PetscCall(PetscOptionsIntArray("-bc_outflow", "Face IDs to apply outflow BC", NULL, bc->outflows, &bc->num_outflow, NULL)); 81487a3b6eSJames Wright // Freestream BCs 82487a3b6eSJames Wright bc->num_freestream = 16; 83487a3b6eSJames Wright PetscCall(PetscOptionsIntArray("-bc_freestream", "Face IDs to apply freestream BC", NULL, bc->freestreams, &bc->num_freestream, NULL)); 84487a3b6eSJames Wright 85*5e79d562SJames Wright PetscCall(PetscOptionsBCDefinition("-bc_slip", "Face IDs to apply slip BC", NULL, "slip", &bc_def, NULL)); 86*5e79d562SJames 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 } 98*5e79d562SJames Wright 99*5e79d562SJames Wright /** 100*5e79d562SJames Wright @brief Destroy `HoneeBCStruct` object 101*5e79d562SJames Wright 102*5e79d562SJames Wright @param[in] ctx Pointer to `HoneeBCStruct` 103*5e79d562SJames Wright **/ 104*5e79d562SJames Wright PetscErrorCode HoneeBCDestroy(void **ctx) { 105*5e79d562SJames Wright HoneeBCStruct honee_bc = *(HoneeBCStruct *)ctx; 106*5e79d562SJames Wright Ceed ceed = honee_bc->honee->ceed; 107*5e79d562SJames Wright 108*5e79d562SJames Wright PetscFunctionBeginUser; 109*5e79d562SJames Wright if (honee_bc->qfctx) PetscCallCeed(ceed, CeedQFunctionContextDestroy(&honee_bc->qfctx)); 110*5e79d562SJames Wright if (honee_bc->DestroyCtx) PetscCall((*(honee_bc->DestroyCtx))(&honee_bc->ctx)); 111*5e79d562SJames Wright PetscCall(PetscFree(honee_bc)); 112*5e79d562SJames Wright *ctx = NULL; 113*5e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 114*5e79d562SJames Wright } 115*5e79d562SJames Wright 116*5e79d562SJames Wright /** 117*5e79d562SJames Wright @brief Create a QFunction matching the "standard" HONEE inputs for IFunctions 118*5e79d562SJames Wright 119*5e79d562SJames Wright This assumes the `bc_def` context is a `HoneeBCStruct` and inputs/outputs of the IFunction QFunction are in the correct order. 120*5e79d562SJames Wright 121*5e79d562SJames Wright @param[in] bc_def `BCDefinition` that hosts the IFunction 122*5e79d562SJames Wright @param[in] qf_func_ptr `CeedQFunctionUser` for the IFunction 123*5e79d562SJames Wright @param[in] qf_loc Absolute path to source of `CeedQFunctionUser` 124*5e79d562SJames Wright @param[in] qfctx `CeedQFunctionContext` for the IFunction (also shared with the IJacobian, if applicable) 125*5e79d562SJames Wright @param[out] qf_ifunc QFunction for the IFunction 126*5e79d562SJames Wright **/ 127*5e79d562SJames Wright PetscErrorCode HoneeBCCreateIFunctionQF(BCDefinition bc_def, CeedQFunctionUser qf_func_ptr, const char *qf_loc, CeedQFunctionContext qfctx, 128*5e79d562SJames Wright CeedQFunction *qf_ifunc) { 129*5e79d562SJames Wright Ceed ceed; 130*5e79d562SJames Wright DM dm; 131*5e79d562SJames Wright PetscInt dim, dim_sur, height = 1, num_comp_x, num_comp_q; 132*5e79d562SJames Wright CeedInt q_data_size_sur, jac_data_size_sur; 133*5e79d562SJames Wright HoneeBCStruct honee_bc; 134*5e79d562SJames Wright 135*5e79d562SJames Wright PetscFunctionBeginUser; 136*5e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 137*5e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 138*5e79d562SJames Wright ceed = honee_bc->honee->ceed; 139*5e79d562SJames Wright jac_data_size_sur = honee_bc->jac_data_size_sur; 140*5e79d562SJames Wright 141*5e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 142*5e79d562SJames Wright dim_sur = dim - height; 143*5e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size_sur)); 144*5e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 145*5e79d562SJames Wright { 146*5e79d562SJames Wright PetscSection section; 147*5e79d562SJames Wright 148*5e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 149*5e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 150*5e79d562SJames Wright } 151*5e79d562SJames Wright 152*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, qf_func_ptr, qf_loc, qf_ifunc)); 153*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(*qf_ifunc, qfctx)); 154*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(*qf_ifunc, 0)); 155*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "q", num_comp_q, CEED_EVAL_INTERP)); 156*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "Grad_q", num_comp_q * dim_sur, CEED_EVAL_GRAD)); 157*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "surface qdata", q_data_size_sur, CEED_EVAL_NONE)); 158*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ifunc, "x", num_comp_x, CEED_EVAL_INTERP)); 159*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ifunc, "v", num_comp_q, CEED_EVAL_INTERP)); 160*5e79d562SJames Wright if (jac_data_size_sur) PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ifunc, "surface jacobian data", jac_data_size_sur, CEED_EVAL_NONE)); 161*5e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 162*5e79d562SJames Wright } 163*5e79d562SJames Wright 164*5e79d562SJames Wright /** 165*5e79d562SJames Wright @brief Create a QFunction matching the "standard" HONEE inputs for IJacobian 166*5e79d562SJames Wright 167*5e79d562SJames Wright This assumes the `bc_def` context is a `HoneeBCStruct` and inputs/outputs of the IJacobian QFunction are in the correct order. 168*5e79d562SJames Wright 169*5e79d562SJames Wright @param[in] bc_def `BCDefinition` that hosts the IJacobian 170*5e79d562SJames Wright @param[in] qf_func_ptr `CeedQFunctionUser` for the IJacobian 171*5e79d562SJames Wright @param[in] qf_loc Absolute path to source of `CeedQFunctionUser` 172*5e79d562SJames Wright @param[in] qfctx `CeedQFunctionContext` for the IJacobian (also shared with the IFunction) 173*5e79d562SJames Wright @param[out] qf_ijac QFunction for the IJacobian 174*5e79d562SJames Wright **/ 175*5e79d562SJames Wright PetscErrorCode HoneeBCCreateIJacobianQF(BCDefinition bc_def, CeedQFunctionUser qf_func_ptr, const char *qf_loc, CeedQFunctionContext qfctx, 176*5e79d562SJames Wright CeedQFunction *qf_ijac) { 177*5e79d562SJames Wright Ceed ceed; 178*5e79d562SJames Wright DM dm; 179*5e79d562SJames Wright PetscInt dim, dim_sur, height = 1, num_comp_x, num_comp_q; 180*5e79d562SJames Wright CeedInt q_data_size_sur, jac_data_size_sur; 181*5e79d562SJames Wright HoneeBCStruct honee_bc; 182*5e79d562SJames Wright 183*5e79d562SJames Wright PetscFunctionBeginUser; 184*5e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 185*5e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 186*5e79d562SJames Wright ceed = honee_bc->honee->ceed; 187*5e79d562SJames Wright jac_data_size_sur = honee_bc->jac_data_size_sur; 188*5e79d562SJames Wright 189*5e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 190*5e79d562SJames Wright dim_sur = dim - height; 191*5e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size_sur)); 192*5e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 193*5e79d562SJames Wright { 194*5e79d562SJames Wright PetscSection section; 195*5e79d562SJames Wright 196*5e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 197*5e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 198*5e79d562SJames Wright } 199*5e79d562SJames Wright 200*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionCreateInterior(ceed, 1, qf_func_ptr, qf_loc, qf_ijac)); 201*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetContext(*qf_ijac, qfctx)); 202*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionSetUserFlopsEstimate(*qf_ijac, 0)); 203*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "dq", num_comp_q, CEED_EVAL_INTERP)); 204*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "Grad_dq", num_comp_q * dim_sur, CEED_EVAL_GRAD)); 205*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "surface qdata", q_data_size_sur, CEED_EVAL_NONE)); 206*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "x", num_comp_x, CEED_EVAL_INTERP)); 207*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddInput(*qf_ijac, "surface jacobian data", jac_data_size_sur, CEED_EVAL_NONE)); 208*5e79d562SJames Wright PetscCallCeed(ceed, CeedQFunctionAddOutput(*qf_ijac, "v", num_comp_q, CEED_EVAL_INTERP)); 209*5e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 210*5e79d562SJames Wright } 211*5e79d562SJames Wright 212*5e79d562SJames Wright /** 213*5e79d562SJames Wright @brief Setups and adds IFunction operator to given composite operator 214*5e79d562SJames Wright 215*5e79d562SJames Wright @param[in] bc_def `BCDefinition` for the boundary condition IFunction 216*5e79d562SJames Wright @param[in] domain_label `DMLabel` for the face orientation label 217*5e79d562SJames Wright @param[in] label_value Orientation value 218*5e79d562SJames Wright @param[in] qf_ifunc QFunction for the IFunction 219*5e79d562SJames Wright @param[in,out] op_ifunc Composite operator to be added to 220*5e79d562SJames Wright @param[out] sub_op_ifunc Non-composite operator that is added in this function. To be passed to `HoneeBCAddIJacobianOp()` 221*5e79d562SJames Wright **/ 222*5e79d562SJames Wright PetscErrorCode HoneeBCAddIFunctionOp(BCDefinition bc_def, DMLabel domain_label, PetscInt label_value, CeedQFunction qf_ifunc, CeedOperator op_ifunc, 223*5e79d562SJames Wright CeedOperator *sub_op_ifunc) { 224*5e79d562SJames Wright Honee honee; 225*5e79d562SJames Wright Ceed ceed; 226*5e79d562SJames Wright DM dm, dm_coord; 227*5e79d562SJames Wright HoneeBCStruct honee_bc; 228*5e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q; 229*5e79d562SJames Wright CeedInt q_data_size, jac_data_size; 230*5e79d562SJames Wright CeedVector q_data, jac_data; 231*5e79d562SJames Wright CeedOperator sub_op_ifunc_; 232*5e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac; 233*5e79d562SJames Wright CeedBasis basis_x, basis_q; 234*5e79d562SJames Wright 235*5e79d562SJames Wright PetscFunctionBeginUser; 236*5e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 237*5e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 238*5e79d562SJames Wright honee = honee_bc->honee; 239*5e79d562SJames Wright ceed = honee_bc->honee->ceed; 240*5e79d562SJames Wright jac_data_size = honee_bc->jac_data_size_sur; 241*5e79d562SJames Wright 242*5e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 243*5e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size)); 244*5e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 245*5e79d562SJames Wright 246*5e79d562SJames Wright { 247*5e79d562SJames Wright PetscSection section; 248*5e79d562SJames Wright 249*5e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 250*5e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 251*5e79d562SJames Wright } 252*5e79d562SJames Wright 253*5e79d562SJames Wright PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 254*5e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &basis_q)); 255*5e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm_coord, domain_label, label_value, height, bc_def->dm_field, &basis_x)); 256*5e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionCreate(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &elem_restr_q)); 257*5e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionCoordinateCreate(ceed, dm, domain_label, label_value, height, &elem_restr_x)); 258*5e79d562SJames Wright if (jac_data_size > 0) { 259*5e79d562SJames Wright PetscCall(DMPlexCeedElemRestrictionQDataCreate(ceed, dm, domain_label, label_value, height, jac_data_size, &elem_restr_jac)); 260*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionCreateVector(elem_restr_jac, &jac_data, NULL)); 261*5e79d562SJames Wright } 262*5e79d562SJames Wright 263*5e79d562SJames 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)); 264*5e79d562SJames Wright 265*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_ifunc, NULL, NULL, &sub_op_ifunc_)); 266*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 267*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "Grad_q", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 268*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface qdata", elem_restr_qd, CEED_BASIS_NONE, q_data)); 269*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "x", elem_restr_x, basis_x, honee->x_coord)); 270*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "v", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 271*5e79d562SJames Wright if (jac_data_size > 0) PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ifunc_, "surface jacobian data", elem_restr_jac, CEED_BASIS_NONE, jac_data)); 272*5e79d562SJames Wright 273*5e79d562SJames Wright PetscCallCeed(ceed, CeedCompositeOperatorAddSub(op_ifunc, sub_op_ifunc_)); 274*5e79d562SJames Wright *sub_op_ifunc = sub_op_ifunc_; 275*5e79d562SJames Wright 276*5e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 277*5e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 278*5e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x)); 279*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 280*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 281*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x)); 282*5e79d562SJames Wright if (jac_data_size > 0) { 283*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac)); 284*5e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data)); 285*5e79d562SJames Wright } 286*5e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 287*5e79d562SJames Wright } 288*5e79d562SJames Wright 289*5e79d562SJames Wright /** 290*5e79d562SJames Wright @brief Setups and adds IJacobian operator to given composite operator 291*5e79d562SJames Wright 292*5e79d562SJames Wright The field data (element restriction, vector, etc) is read from `sub_op_ifunc` and used for the IJacobian. 293*5e79d562SJames Wright 294*5e79d562SJames Wright @param[in] bc_def `BCDefinition` for the boundary condition IJacobian 295*5e79d562SJames Wright @param[out] sub_op_ifunc IFunction operator corresponding to this IJacobian operator. 296*5e79d562SJames Wright @param[in] domain_label `DMLabel` for the face orientation label 297*5e79d562SJames Wright @param[in] label_value Orientation value 298*5e79d562SJames Wright @param[in] qf_ijac QFunction for the IJacobian 299*5e79d562SJames Wright @param[in,out] op_ijac Composite operator to be added to 300*5e79d562SJames Wright **/ 301*5e79d562SJames Wright PetscErrorCode HoneeBCAddIJacobianOp(BCDefinition bc_def, CeedOperator sub_op_ifunc, DMLabel domain_label, PetscInt label_value, 302*5e79d562SJames Wright CeedQFunction qf_ijac, CeedOperator op_ijac) { 303*5e79d562SJames Wright Honee honee; 304*5e79d562SJames Wright Ceed ceed; 305*5e79d562SJames Wright DM dm, dm_coord; 306*5e79d562SJames Wright HoneeBCStruct honee_bc; 307*5e79d562SJames Wright PetscInt dim, height = 1, num_comp_x, num_comp_q; 308*5e79d562SJames Wright CeedInt q_data_size; 309*5e79d562SJames Wright CeedVector q_data, jac_data; 310*5e79d562SJames Wright CeedElemRestriction elem_restr_qd, elem_restr_q, elem_restr_x, elem_restr_jac; 311*5e79d562SJames Wright CeedOperator sub_op_ijac; 312*5e79d562SJames Wright CeedBasis basis_x, basis_q; 313*5e79d562SJames Wright 314*5e79d562SJames Wright PetscFunctionBeginUser; 315*5e79d562SJames Wright PetscCall(BCDefinitionGetContext(bc_def, &honee_bc)); 316*5e79d562SJames Wright if (honee_bc->jac_data_size_sur == 0) PetscFunctionReturn(PETSC_SUCCESS); 317*5e79d562SJames Wright PetscCall(BCDefinitionGetDM(bc_def, &dm)); 318*5e79d562SJames Wright honee = honee_bc->honee; 319*5e79d562SJames Wright ceed = honee_bc->honee->ceed; 320*5e79d562SJames Wright 321*5e79d562SJames Wright PetscCall(DMGetDimension(dm, &dim)); 322*5e79d562SJames Wright PetscCall(QDataBoundaryGetNumComponents(dm, &q_data_size)); 323*5e79d562SJames Wright PetscCall(DMGetCoordinateNumComps(dm, &num_comp_x)); 324*5e79d562SJames Wright 325*5e79d562SJames Wright { 326*5e79d562SJames Wright PetscSection section; 327*5e79d562SJames Wright 328*5e79d562SJames Wright PetscCall(DMGetLocalSection(dm, §ion)); 329*5e79d562SJames Wright PetscCall(PetscSectionGetFieldComponents(section, bc_def->dm_field, &num_comp_q)); 330*5e79d562SJames Wright } 331*5e79d562SJames Wright 332*5e79d562SJames Wright PetscCall(DMGetCoordinateDM(dm, &dm_coord)); 333*5e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm, domain_label, label_value, height, bc_def->dm_field, &basis_q)); 334*5e79d562SJames Wright PetscCall(CreateBasisFromPlex(ceed, dm_coord, domain_label, label_value, height, bc_def->dm_field, &basis_x)); 335*5e79d562SJames Wright 336*5e79d562SJames Wright { // Get restriction and basis from the RHS function 337*5e79d562SJames Wright CeedOperatorField op_field; 338*5e79d562SJames Wright 339*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "q", &op_field)); 340*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetElemRestriction(op_field, &elem_restr_q)); 341*5e79d562SJames Wright 342*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "x", &op_field)); 343*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetElemRestriction(op_field, &elem_restr_x)); 344*5e79d562SJames Wright 345*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorGetFieldByName(sub_op_ifunc, "surface jacobian data", &op_field)); 346*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorFieldGetData(op_field, NULL, &elem_restr_jac, NULL, &jac_data)); 347*5e79d562SJames Wright } 348*5e79d562SJames Wright 349*5e79d562SJames 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)); 350*5e79d562SJames Wright 351*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorCreate(ceed, qf_ijac, NULL, NULL, &sub_op_ijac)); 352*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "dq", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 353*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "Grad_dq", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 354*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "surface qdata", elem_restr_qd, CEED_BASIS_NONE, q_data)); 355*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "x", elem_restr_x, basis_x, honee->x_coord)); 356*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "surface jacobian data", elem_restr_jac, CEED_BASIS_NONE, jac_data)); 357*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorSetField(sub_op_ijac, "v", elem_restr_q, basis_q, CEED_VECTOR_ACTIVE)); 358*5e79d562SJames Wright 359*5e79d562SJames Wright PetscCallCeed(ceed, CeedCompositeOperatorAddSub(op_ijac, sub_op_ijac)); 360*5e79d562SJames Wright 361*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_q)); 362*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_x)); 363*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_jac)); 364*5e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&jac_data)); 365*5e79d562SJames Wright PetscCallCeed(ceed, CeedVectorDestroy(&q_data)); 366*5e79d562SJames Wright PetscCallCeed(ceed, CeedElemRestrictionDestroy(&elem_restr_qd)); 367*5e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_q)); 368*5e79d562SJames Wright PetscCallCeed(ceed, CeedBasisDestroy(&basis_x)); 369*5e79d562SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ijac)); 370*5e79d562SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 371*5e79d562SJames Wright } 372