1ae2b091fSJames Wright // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors. 2ae2b091fSJames Wright // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 3487a3b6eSJames Wright 4487a3b6eSJames Wright #include <bc_definition.h> 577aa5ad7SJames Wright #include <dm-utils.h> 677aa5ad7SJames Wright #include <petsc-ceed.h> 709240e0aSJames Wright #include <petsc/private/petscimpl.h> 8487a3b6eSJames Wright 9*96f347c2SJames Wright PetscClassId BC_DEFINITION_CLASSID; 10*96f347c2SJames Wright 11*96f347c2SJames Wright /** 12*96f347c2SJames Wright @brief Initalize `BCDefinition` class. 13*96f347c2SJames Wright 14*96f347c2SJames Wright Not collective across MPI processes. 15*96f347c2SJames Wright 16*96f347c2SJames Wright @return An error code: 0 - success, otherwise - failure 17*96f347c2SJames Wright **/ 18*96f347c2SJames Wright static PetscErrorCode BCDefinitionInitalize() { 19*96f347c2SJames Wright static PetscBool registered = PETSC_FALSE; 20*96f347c2SJames Wright 21*96f347c2SJames Wright PetscFunctionBeginUser; 22*96f347c2SJames Wright if (registered) PetscFunctionReturn(PETSC_SUCCESS); 23*96f347c2SJames Wright PetscCall(PetscClassIdRegister("BCDefinition", &BC_DEFINITION_CLASSID)); 24*96f347c2SJames Wright registered = PETSC_TRUE; 25*96f347c2SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 26*96f347c2SJames Wright } 27*96f347c2SJames Wright 28487a3b6eSJames Wright /** 29487a3b6eSJames Wright @brief Create `BCDefinition` 30487a3b6eSJames Wright 31*96f347c2SJames Wright @param[in] comm `MPI_Comm` for the object 32487a3b6eSJames Wright @param[in] name Name of the boundary condition 33487a3b6eSJames Wright @param[in] num_label_values Number of `DMLabel` values 34487a3b6eSJames Wright @param[in] label_values Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values` 35487a3b6eSJames Wright @param[out] bc_def The new `BCDefinition` 36487a3b6eSJames Wright **/ 37*96f347c2SJames Wright PetscErrorCode BCDefinitionCreate(MPI_Comm comm, const char *name, PetscInt num_label_values, PetscInt label_values[], BCDefinition *bc_def) { 38*96f347c2SJames Wright BCDefinition bc_def_; 39487a3b6eSJames Wright 40*96f347c2SJames Wright PetscFunctionBeginUser; 41*96f347c2SJames Wright PetscCall(BCDefinitionInitalize()); 42*96f347c2SJames Wright PetscCall( 43*96f347c2SJames Wright PetscHeaderCreate(bc_def_, BC_DEFINITION_CLASSID, "BCDefinition", "BCDefinition", "BCDefinition", comm, BCDefinitionDestroy, BCDefinitionView)); 44*96f347c2SJames Wright 45*96f347c2SJames Wright PetscCall(PetscStrallocpy(name, &bc_def_->name)); 46*96f347c2SJames Wright PetscCall(PetscObjectSetName((PetscObject)bc_def_, name)); 47*96f347c2SJames Wright bc_def_->num_label_values = num_label_values; 48*96f347c2SJames Wright PetscCall(PetscMalloc1(num_label_values, &bc_def_->label_values)); 49*96f347c2SJames Wright for (PetscInt i = 0; i < num_label_values; i++) bc_def_->label_values[i] = label_values[i]; 50*96f347c2SJames Wright *bc_def = bc_def_; 51*96f347c2SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 52*96f347c2SJames Wright } 53*96f347c2SJames Wright 54*96f347c2SJames Wright /** 55*96f347c2SJames Wright @brief Destory a `BCDefinition` object 56*96f347c2SJames Wright 57*96f347c2SJames Wright @param[in,out] bc_def `BCDefinition` to be destroyed 58*96f347c2SJames Wright **/ 59*96f347c2SJames Wright PetscErrorCode BCDefinitionDestroy(BCDefinition *bc_def) { 60*96f347c2SJames Wright BCDefinition bc_def_ = *bc_def; 61*96f347c2SJames Wright PetscFunctionBeginUser; 62*96f347c2SJames Wright if (!bc_def_) PetscFunctionReturn(PETSC_SUCCESS); 63*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def_, BC_DEFINITION_CLASSID, 1); 64*96f347c2SJames Wright if (bc_def_->name) PetscCall(PetscFree(bc_def_->name)); 65*96f347c2SJames Wright if (bc_def_->label_values) PetscCall(PetscFree(bc_def_->label_values)); 66*96f347c2SJames Wright if (bc_def_->essential_comps) PetscCall(PetscFree(bc_def_->essential_comps)); 67*96f347c2SJames Wright if (bc_def_->dm) PetscCall(DMDestroy(&bc_def_->dm)); 68*96f347c2SJames Wright if (bc_def_->DestroyCtx) PetscCall((*(bc_def_->DestroyCtx))(&bc_def_->ctx)); 69*96f347c2SJames Wright PetscCall(PetscHeaderDestroy(&bc_def_)); 70*96f347c2SJames Wright *bc_def = NULL; 71*96f347c2SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 72*96f347c2SJames Wright } 73*96f347c2SJames Wright 74*96f347c2SJames Wright /** 75*96f347c2SJames Wright @brief View a `BCDefinition` object. 76*96f347c2SJames Wright 77*96f347c2SJames Wright Not collective across MPI processes. 78*96f347c2SJames Wright 79*96f347c2SJames Wright @param[in] bc_def `BCDefinition` object 80*96f347c2SJames Wright @param[in] viewer Optional `PetscViewer` context or `NULL` 81*96f347c2SJames Wright 82*96f347c2SJames Wright @return An error code: 0 - success, otherwise - failure 83*96f347c2SJames Wright **/ 84*96f347c2SJames Wright PetscErrorCode BCDefinitionView(BCDefinition bc_def, PetscViewer viewer) { 85*96f347c2SJames Wright PetscBool is_ascii; 86*96f347c2SJames Wright PetscViewerFormat format; 87*96f347c2SJames Wright PetscMPIInt size; 88*96f347c2SJames Wright 89*96f347c2SJames Wright PetscFunctionBeginUser; 90*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 91*96f347c2SJames Wright PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 92*96f347c2SJames Wright if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)bc_def), &viewer)); 93*96f347c2SJames Wright 94*96f347c2SJames Wright PetscCall(PetscViewerGetFormat(viewer, &format)); 95*96f347c2SJames Wright PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)bc_def), &size)); 96*96f347c2SJames Wright if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 97*96f347c2SJames Wright 98*96f347c2SJames Wright PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii)); 99*96f347c2SJames Wright { 100*96f347c2SJames Wright PetscBool is_detailed = format == PETSC_VIEWER_ASCII_INFO_DETAIL; 101*96f347c2SJames Wright 102*96f347c2SJames Wright PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)bc_def, viewer)); 103*96f347c2SJames Wright PetscCall(PetscViewerASCIIPushTab(viewer)); // BCDefinition 104*96f347c2SJames Wright 105*96f347c2SJames Wright if (is_detailed) PetscCall(DMView(bc_def->dm, viewer)); 106*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "DM Field: %" PetscInt_FMT "\n", bc_def->dm_field)); 107*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "Face Sets:")); 108*96f347c2SJames Wright PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 109*96f347c2SJames Wright if (bc_def->num_label_values > 0) { 110*96f347c2SJames Wright for (PetscInt i = 0; i < bc_def->num_label_values; i++) { 111*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, bc_def->label_values[i])); 112*96f347c2SJames Wright } 113*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 114*96f347c2SJames Wright } else { 115*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " None\n")); 116*96f347c2SJames Wright } 117*96f347c2SJames Wright PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 118*96f347c2SJames Wright 119*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "Essential Components:")); 120*96f347c2SJames Wright PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 121*96f347c2SJames Wright if (bc_def->num_essential_comps > 0) { 122*96f347c2SJames Wright for (PetscInt i = 0; i < bc_def->num_essential_comps; i++) { 123*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, bc_def->essential_comps[i])); 124*96f347c2SJames Wright } 125*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 126*96f347c2SJames Wright } else { 127*96f347c2SJames Wright PetscCall(PetscViewerASCIIPrintf(viewer, " None\n")); 128*96f347c2SJames Wright } 129*96f347c2SJames Wright PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 130*96f347c2SJames Wright 131*96f347c2SJames Wright PetscCall(PetscViewerASCIIPopTab(viewer)); // BCDefinition 132*96f347c2SJames Wright } 133*96f347c2SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 134*96f347c2SJames Wright } 135*96f347c2SJames Wright 136*96f347c2SJames Wright /** 137*96f347c2SJames Wright @brief View `BCDefinition` from options database (command line/YAML) 138*96f347c2SJames Wright 139*96f347c2SJames Wright @param[in] bc_def `BCDefintion` to view 140*96f347c2SJames Wright @param[in] obj Optional object that provides the prefix for the options database (if `NULL` then the prefix in `bc_def` is used) 141*96f347c2SJames Wright @param[in] name Option string that is used to activate viewing 142*96f347c2SJames Wright **/ 143*96f347c2SJames Wright PetscErrorCode BCDefinitionViewFromOptions(BCDefinition bc_def, PetscObject obj, const char name[]) { 144*96f347c2SJames Wright PetscFunctionBegin; 145*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 146*96f347c2SJames Wright PetscCall(PetscObjectViewFromOptions((PetscObject)bc_def, obj, name)); 147487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 148487a3b6eSJames Wright } 149487a3b6eSJames Wright 150487a3b6eSJames Wright /** 151487a3b6eSJames Wright @brief Get base information for `BCDefinition` 152487a3b6eSJames Wright 153487a3b6eSJames Wright @param[in] bc_def `BCDefinition` to get information from 154487a3b6eSJames Wright @param[out] name Name of the `BCDefinition` 155487a3b6eSJames Wright @param[out] num_label_values Number of `DMLabel` values 156487a3b6eSJames Wright @param[out] label_values Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values` 157487a3b6eSJames Wright **/ 158487a3b6eSJames Wright PetscErrorCode BCDefinitionGetInfo(BCDefinition bc_def, const char *name[], PetscInt *num_label_values, const PetscInt *label_values[]) { 159487a3b6eSJames Wright PetscFunctionBeginUser; 160*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 1610990a807SJames Wright if (name) { 1620990a807SJames Wright PetscAssertPointer(name, 2); 1630990a807SJames Wright *name = bc_def->name; 1640990a807SJames Wright } 165487a3b6eSJames Wright if (label_values) { 1660990a807SJames Wright PetscAssertPointer(num_label_values, 3); 1670990a807SJames Wright PetscAssertPointer(label_values, 4); 168487a3b6eSJames Wright *num_label_values = bc_def->num_label_values; 169487a3b6eSJames Wright *label_values = bc_def->label_values; 170487a3b6eSJames Wright } 171487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 172487a3b6eSJames Wright } 173487a3b6eSJames Wright 174487a3b6eSJames Wright /** 175487a3b6eSJames Wright @brief Set `DM_BC_ESSENTIAL` boundary condition values 176487a3b6eSJames Wright 177487a3b6eSJames Wright @param[in,out] bc_def `BCDefinition` to set values to 178487a3b6eSJames Wright @param[in] num_essential_comps Number of components to set 179487a3b6eSJames Wright @param[in] essential_comps Array of components to set, size `num_essential_comps` 180487a3b6eSJames Wright **/ 181487a3b6eSJames Wright PetscErrorCode BCDefinitionSetEssential(BCDefinition bc_def, PetscInt num_essential_comps, PetscInt essential_comps[]) { 182487a3b6eSJames Wright PetscFunctionBeginUser; 183*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 184487a3b6eSJames Wright bc_def->num_essential_comps = num_essential_comps; 185487a3b6eSJames Wright PetscCall(PetscMalloc1(num_essential_comps, &bc_def->essential_comps)); 186487a3b6eSJames Wright PetscCall(PetscArraycpy(bc_def->essential_comps, essential_comps, num_essential_comps)); 187487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 188487a3b6eSJames Wright } 189487a3b6eSJames Wright 190487a3b6eSJames Wright /** 191487a3b6eSJames Wright @brief Get `DM_BC_ESSENTIAL` boundary condition values 192487a3b6eSJames Wright 193487a3b6eSJames Wright @param[in] bc_def `BCDefinition` to set values to 194487a3b6eSJames Wright @param[out] num_essential_comps Number of components to set 195487a3b6eSJames Wright @param[out] essential_comps Array of components to set, size `num_essential_comps` 196487a3b6eSJames Wright **/ 197487a3b6eSJames Wright PetscErrorCode BCDefinitionGetEssential(BCDefinition bc_def, PetscInt *num_essential_comps, const PetscInt *essential_comps[]) { 198487a3b6eSJames Wright PetscFunctionBeginUser; 199*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 2000990a807SJames Wright PetscAssertPointer(num_essential_comps, 2); 2010990a807SJames Wright PetscAssertPointer(essential_comps, 3); 202487a3b6eSJames Wright *num_essential_comps = bc_def->num_essential_comps; 203487a3b6eSJames Wright *essential_comps = bc_def->essential_comps; 204487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 205487a3b6eSJames Wright } 206487a3b6eSJames Wright 207487a3b6eSJames Wright #define LABEL_ARRAY_SIZE 256 208487a3b6eSJames Wright 209487a3b6eSJames Wright // @brief See `PetscOptionsBCDefinition` 210ddf6e248SJames Wright PetscErrorCode PetscOptionsBCDefinition_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], 211487a3b6eSJames Wright const char name[], BCDefinition *bc_def, PetscBool *set) { 212487a3b6eSJames Wright PetscInt num_label_values = LABEL_ARRAY_SIZE, label_values[LABEL_ARRAY_SIZE] = {0}; 213487a3b6eSJames Wright 214487a3b6eSJames Wright PetscFunctionBeginUser; 215487a3b6eSJames Wright PetscCall(PetscOptionsIntArray(opt, text, man, label_values, &num_label_values, set)); 216487a3b6eSJames Wright if (num_label_values > 0) { 217*96f347c2SJames Wright PetscCall(BCDefinitionCreate(PetscOptionsObject->comm, name, num_label_values, label_values, bc_def)); 218487a3b6eSJames Wright } else { 219487a3b6eSJames Wright *bc_def = NULL; 220487a3b6eSJames Wright } 221487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 222487a3b6eSJames Wright } 22309240e0aSJames Wright 22409240e0aSJames Wright /** 22509240e0aSJames Wright @brief Set `DM` for BCDefinition 22609240e0aSJames Wright 22709240e0aSJames Wright @param[in,out] bc_def `BCDefinition` to add `dm` to 22809240e0aSJames Wright @param[in] dm `DM` to assign to BCDefinition, or `NULL` to remove `DM` 22909240e0aSJames Wright **/ 23009240e0aSJames Wright PetscErrorCode BCDefinitionSetDM(BCDefinition bc_def, DM dm) { 23109240e0aSJames Wright PetscFunctionBeginUser; 232*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 23309240e0aSJames Wright if (bc_def->dm) PetscCall(DMDestroy(&bc_def->dm)); 23409240e0aSJames Wright if (dm) { 23509240e0aSJames Wright PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 23609240e0aSJames Wright PetscCall(PetscObjectReference((PetscObject)dm)); 23709240e0aSJames Wright bc_def->dm = dm; 23809240e0aSJames Wright } 23909240e0aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 24009240e0aSJames Wright } 24109240e0aSJames Wright 24209240e0aSJames Wright /** 24309240e0aSJames Wright @brief Get `DM` assigned to BCDefinition 24409240e0aSJames Wright 24509240e0aSJames Wright @param[in] bc_def `BCDefinition` to get `dm` from 24609240e0aSJames Wright @param[out] dm `DM` assigned to BCDefinition 24709240e0aSJames Wright **/ 24809240e0aSJames Wright PetscErrorCode BCDefinitionGetDM(BCDefinition bc_def, DM *dm) { 249*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 25009240e0aSJames Wright PetscFunctionBeginUser; 25109240e0aSJames Wright PetscAssertPointer(dm, 2); 25209240e0aSJames Wright *dm = bc_def->dm; 25309240e0aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 25409240e0aSJames Wright } 2552e678684SJames Wright 2562e678684SJames Wright /** 2572e678684SJames Wright @brief Set custom context struct for use in BCDefinition 2582e678684SJames Wright 2592e678684SJames Wright @param[in,out] bc_def `BCDefinition` to add `ctx` to 2602e678684SJames Wright @param[in] destroy_ctx Optional function pointer that destroys the user context on `BCDefinitionDestroy()` 2612e678684SJames Wright @param[in] ctx Pointer to context struct 2622e678684SJames Wright **/ 2632e678684SJames Wright PetscErrorCode BCDefinitionSetContext(BCDefinition bc_def, PetscCtxDestroyFn *destroy_ctx, void *ctx) { 2642e678684SJames Wright PetscFunctionBeginUser; 265*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 2662e678684SJames Wright if (bc_def->DestroyCtx) PetscCall((*(bc_def->DestroyCtx))(&bc_def->ctx)); 2672e678684SJames Wright bc_def->ctx = ctx; 2682e678684SJames Wright bc_def->DestroyCtx = destroy_ctx; 2692e678684SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2702e678684SJames Wright } 2712e678684SJames Wright 2722e678684SJames Wright /** 2732e678684SJames Wright @brief Set custom context struct for use in BCDefinition 2742e678684SJames Wright 2752e678684SJames Wright @param[in] bc_def `BCDefinition` to get `ctx` from 2762e678684SJames Wright @param[out] ctx Pointer to context struct 2772e678684SJames Wright **/ 2782e678684SJames Wright PetscErrorCode BCDefinitionGetContext(BCDefinition bc_def, void *ctx) { 2792e678684SJames Wright PetscFunctionBeginUser; 280*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 2812e678684SJames Wright PetscAssertPointer(ctx, 2); 2822e678684SJames Wright *(void **)ctx = bc_def->ctx; 2832e678684SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 2842e678684SJames Wright } 28577aa5ad7SJames Wright 28677aa5ad7SJames Wright /** 28777aa5ad7SJames Wright @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IFunction of boundary condition 28877aa5ad7SJames Wright 28977aa5ad7SJames Wright @param[in,out] bc_def `BCDefinition` to add function pointers to 29077aa5ad7SJames Wright @param[in] create_qf Function to create `CeedQFunction` 29177aa5ad7SJames Wright @param[in] add_op Function to create and add `CeedOperator` to composite `CeedOperator` 29277aa5ad7SJames Wright **/ 29377aa5ad7SJames Wright PetscErrorCode BCDefinitionSetIFunction(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIFunctionOperator add_op) { 29477aa5ad7SJames Wright PetscFunctionBeginUser; 295*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 29677aa5ad7SJames Wright bc_def->CreateIFunctionQF = create_qf; 29777aa5ad7SJames Wright bc_def->AddIFunctionOperator = add_op; 29877aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 29977aa5ad7SJames Wright } 30077aa5ad7SJames Wright 30177aa5ad7SJames Wright /** 30277aa5ad7SJames Wright @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IJacobian of boundary condition 30377aa5ad7SJames Wright 30477aa5ad7SJames Wright @param[in,out] bc_def `BCDefinition` to add function pointers to 30577aa5ad7SJames Wright @param[in] create_qf Function to create `CeedQFunction` 30677aa5ad7SJames Wright @param[in] add_op Function to create and add `CeedOperator` to composite `CeedOperator` 30777aa5ad7SJames Wright **/ 30877aa5ad7SJames Wright PetscErrorCode BCDefinitionSetIJacobian(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIJacobianOperator add_op) { 30977aa5ad7SJames Wright PetscFunctionBeginUser; 310*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 31177aa5ad7SJames Wright bc_def->CreateIJacobianQF = create_qf; 31277aa5ad7SJames Wright bc_def->AddIJacobianOperator = add_op; 31377aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 31477aa5ad7SJames Wright } 31577aa5ad7SJames Wright 31677aa5ad7SJames Wright /** 31777aa5ad7SJames Wright @brief Add operators (IFunction, IJacobian) to composite operator 31877aa5ad7SJames Wright 31977aa5ad7SJames Wright This loops over orientations for each face label specified by `bc_def` and adds the IFunction and IJacobian operator to respective composite operator. 32077aa5ad7SJames Wright 32177aa5ad7SJames Wright @param[in] bc_def `BCDefinition` from which operators are created and added 32277aa5ad7SJames Wright @param[in,out] op_ifunc Composite operator for IFunction operators to be added to 32377aa5ad7SJames Wright @param[in,out] op_ijac Composite operator for IJacobian operators to be added to 32477aa5ad7SJames Wright **/ 32577aa5ad7SJames Wright PetscErrorCode BCDefinitionAddOperators(BCDefinition bc_def, CeedOperator op_ifunc, CeedOperator op_ijac) { 32677aa5ad7SJames Wright Ceed ceed = CeedOperatorReturnCeed(op_ifunc); 32777aa5ad7SJames Wright CeedQFunction qf_ifunction, qf_ijacobian; 32877aa5ad7SJames Wright DMLabel face_sets_label; 32977aa5ad7SJames Wright PetscInt num_face_set_values; 33077aa5ad7SJames Wright const PetscInt *face_set_values; 33177aa5ad7SJames Wright 33277aa5ad7SJames Wright PetscFunctionBeginUser; 333*96f347c2SJames Wright PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1); 33477aa5ad7SJames Wright if (!bc_def->CreateIFunctionQF || !bc_def->AddIFunctionOperator) PetscFunctionReturn(PETSC_SUCCESS); 335ea091b8eSJames Wright PetscBool add_ijac = (!bc_def->CreateIJacobianQF || !bc_def->AddIJacobianOperator || !op_ijac) ? PETSC_FALSE : PETSC_TRUE; 33677aa5ad7SJames Wright PetscCheck(bc_def->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "BCDefinition must have DM set using BCDefinitionSetDM()"); 33777aa5ad7SJames Wright 33877aa5ad7SJames Wright PetscCall(bc_def->CreateIFunctionQF(bc_def, &qf_ifunction)); 33977aa5ad7SJames Wright if (add_ijac) PetscCall(bc_def->CreateIJacobianQF(bc_def, &qf_ijacobian)); 34077aa5ad7SJames Wright 34177aa5ad7SJames Wright PetscCall(DMGetLabel(bc_def->dm, "Face Sets", &face_sets_label)); 34277aa5ad7SJames Wright PetscCall(BCDefinitionGetInfo(bc_def, NULL, &num_face_set_values, &face_set_values)); 34377aa5ad7SJames Wright for (PetscInt f = 0; f < num_face_set_values; f++) { 34477aa5ad7SJames Wright DMLabel face_orientation_label; 34577aa5ad7SJames Wright PetscInt num_orientations_values, *orientation_values; 34677aa5ad7SJames Wright 34777aa5ad7SJames Wright { 34877aa5ad7SJames Wright char *face_orientation_label_name; 34977aa5ad7SJames Wright 35077aa5ad7SJames Wright PetscCall(DMPlexCreateFaceLabel(bc_def->dm, face_set_values[f], &face_orientation_label_name)); 35177aa5ad7SJames Wright PetscCall(DMGetLabel(bc_def->dm, face_orientation_label_name, &face_orientation_label)); 35277aa5ad7SJames Wright PetscCall(PetscFree(face_orientation_label_name)); 35377aa5ad7SJames Wright } 35477aa5ad7SJames Wright PetscCall(DMLabelCreateGlobalValueArray(bc_def->dm, face_orientation_label, &num_orientations_values, &orientation_values)); 35577aa5ad7SJames Wright for (PetscInt o = 0; o < num_orientations_values; o++) { 35677aa5ad7SJames Wright CeedOperator sub_op_ifunc; 35777aa5ad7SJames Wright PetscInt orientation = orientation_values[o]; 35877aa5ad7SJames Wright 35977aa5ad7SJames Wright PetscCall(bc_def->AddIFunctionOperator(bc_def, face_orientation_label, orientation, qf_ifunction, op_ifunc, &sub_op_ifunc)); 36077aa5ad7SJames Wright if (add_ijac) PetscCall(bc_def->AddIJacobianOperator(bc_def, sub_op_ifunc, face_orientation_label, orientation, qf_ijacobian, op_ijac)); 36177aa5ad7SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ifunc)); 36277aa5ad7SJames Wright } 36377aa5ad7SJames Wright PetscCall(PetscFree(orientation_values)); 36477aa5ad7SJames Wright } 36577aa5ad7SJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ifunction)); 36677aa5ad7SJames Wright if (add_ijac) PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ijacobian)); 36777aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 36877aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 36977aa5ad7SJames Wright } 370