1 // SPDX-FileCopyrightText: Copyright (c) 2017-2024, HONEE contributors. 2 // SPDX-License-Identifier: Apache-2.0 OR BSD-2-Clause 3 4 #include <bc_definition.h> 5 #include <dm-utils.h> 6 #include <petsc-ceed.h> 7 #include <petsc/private/petscimpl.h> 8 9 /** 10 @brief Create `BCDefinition` 11 12 @param[in] name Name of the boundary condition 13 @param[in] num_label_values Number of `DMLabel` values 14 @param[in] label_values Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values` 15 @param[out] bc_def The new `BCDefinition` 16 **/ 17 PetscErrorCode BCDefinitionCreate(const char *name, PetscInt num_label_values, PetscInt label_values[], BCDefinition *bc_def) { 18 PetscFunctionBeginUser; 19 PetscCall(PetscNew(bc_def)); 20 21 PetscCall(PetscStrallocpy(name, &(*bc_def)->name)); 22 (*bc_def)->num_label_values = num_label_values; 23 PetscCall(PetscMalloc1(num_label_values, &(*bc_def)->label_values)); 24 for (PetscInt i = 0; i < num_label_values; i++) (*bc_def)->label_values[i] = label_values[i]; 25 PetscFunctionReturn(PETSC_SUCCESS); 26 } 27 28 /** 29 @brief Get base information for `BCDefinition` 30 31 @param[in] bc_def `BCDefinition` to get information from 32 @param[out] name Name of the `BCDefinition` 33 @param[out] num_label_values Number of `DMLabel` values 34 @param[out] label_values Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values` 35 **/ 36 PetscErrorCode BCDefinitionGetInfo(BCDefinition bc_def, const char *name[], PetscInt *num_label_values, const PetscInt *label_values[]) { 37 PetscFunctionBeginUser; 38 if (name) *name = bc_def->name; 39 if (label_values) { 40 *num_label_values = bc_def->num_label_values; 41 *label_values = bc_def->label_values; 42 } 43 PetscFunctionReturn(PETSC_SUCCESS); 44 } 45 46 /** 47 @brief Destory a `BCDefinition` object 48 49 @param[in,out] bc_def `BCDefinition` to be destroyed 50 **/ 51 PetscErrorCode BCDefinitionDestroy(BCDefinition *bc_def) { 52 BCDefinition bc_def_ = *bc_def; 53 PetscFunctionBeginUser; 54 if (bc_def_->name) PetscCall(PetscFree(bc_def_->name)); 55 if (bc_def_->label_values) PetscCall(PetscFree(bc_def_->label_values)); 56 if (bc_def_->essential_comps) PetscCall(PetscFree(bc_def_->essential_comps)); 57 if (bc_def_->dm) PetscCall(DMDestroy(&bc_def_->dm)); 58 if (bc_def_->DestroyCtx) PetscCall((*(bc_def_->DestroyCtx))(&bc_def_->ctx)); 59 PetscCall(PetscFree(bc_def_)); 60 *bc_def = NULL; 61 PetscFunctionReturn(PETSC_SUCCESS); 62 } 63 64 /** 65 @brief Set `DM_BC_ESSENTIAL` boundary condition values 66 67 @param[in,out] bc_def `BCDefinition` to set values to 68 @param[in] num_essential_comps Number of components to set 69 @param[in] essential_comps Array of components to set, size `num_essential_comps` 70 **/ 71 PetscErrorCode BCDefinitionSetEssential(BCDefinition bc_def, PetscInt num_essential_comps, PetscInt essential_comps[]) { 72 PetscFunctionBeginUser; 73 bc_def->num_essential_comps = num_essential_comps; 74 PetscCall(PetscMalloc1(num_essential_comps, &bc_def->essential_comps)); 75 PetscCall(PetscArraycpy(bc_def->essential_comps, essential_comps, num_essential_comps)); 76 PetscFunctionReturn(PETSC_SUCCESS); 77 } 78 79 /** 80 @brief Get `DM_BC_ESSENTIAL` boundary condition values 81 82 @param[in] bc_def `BCDefinition` to set values to 83 @param[out] num_essential_comps Number of components to set 84 @param[out] essential_comps Array of components to set, size `num_essential_comps` 85 **/ 86 PetscErrorCode BCDefinitionGetEssential(BCDefinition bc_def, PetscInt *num_essential_comps, const PetscInt *essential_comps[]) { 87 PetscFunctionBeginUser; 88 *num_essential_comps = bc_def->num_essential_comps; 89 *essential_comps = bc_def->essential_comps; 90 PetscFunctionReturn(PETSC_SUCCESS); 91 } 92 93 #define LABEL_ARRAY_SIZE 256 94 95 // @brief See `PetscOptionsBCDefinition` 96 PetscErrorCode PetscOptionsBCDefinition_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], 97 const char name[], BCDefinition *bc_def, PetscBool *set) { 98 PetscInt num_label_values = LABEL_ARRAY_SIZE, label_values[LABEL_ARRAY_SIZE] = {0}; 99 100 PetscFunctionBeginUser; 101 PetscCall(PetscOptionsIntArray(opt, text, man, label_values, &num_label_values, set)); 102 if (num_label_values > 0) { 103 PetscCall(BCDefinitionCreate(name, num_label_values, label_values, bc_def)); 104 } else { 105 *bc_def = NULL; 106 } 107 PetscFunctionReturn(PETSC_SUCCESS); 108 } 109 110 /** 111 @brief Set `DM` for BCDefinition 112 113 @param[in,out] bc_def `BCDefinition` to add `dm` to 114 @param[in] dm `DM` to assign to BCDefinition, or `NULL` to remove `DM` 115 **/ 116 PetscErrorCode BCDefinitionSetDM(BCDefinition bc_def, DM dm) { 117 PetscFunctionBeginUser; 118 if (bc_def->dm) PetscCall(DMDestroy(&bc_def->dm)); 119 if (dm) { 120 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 121 PetscCall(PetscObjectReference((PetscObject)dm)); 122 bc_def->dm = dm; 123 } 124 PetscFunctionReturn(PETSC_SUCCESS); 125 } 126 127 /** 128 @brief Get `DM` assigned to BCDefinition 129 130 @param[in] bc_def `BCDefinition` to get `dm` from 131 @param[out] dm `DM` assigned to BCDefinition 132 **/ 133 PetscErrorCode BCDefinitionGetDM(BCDefinition bc_def, DM *dm) { 134 PetscFunctionBeginUser; 135 PetscAssertPointer(dm, 2); 136 *dm = bc_def->dm; 137 PetscFunctionReturn(PETSC_SUCCESS); 138 } 139 140 /** 141 @brief Set custom context struct for use in BCDefinition 142 143 @param[in,out] bc_def `BCDefinition` to add `ctx` to 144 @param[in] destroy_ctx Optional function pointer that destroys the user context on `BCDefinitionDestroy()` 145 @param[in] ctx Pointer to context struct 146 **/ 147 PetscErrorCode BCDefinitionSetContext(BCDefinition bc_def, PetscCtxDestroyFn *destroy_ctx, void *ctx) { 148 PetscFunctionBeginUser; 149 if (bc_def->DestroyCtx) PetscCall((*(bc_def->DestroyCtx))(&bc_def->ctx)); 150 bc_def->ctx = ctx; 151 bc_def->DestroyCtx = destroy_ctx; 152 PetscFunctionReturn(PETSC_SUCCESS); 153 } 154 155 /** 156 @brief Set custom context struct for use in BCDefinition 157 158 @param[in] bc_def `BCDefinition` to get `ctx` from 159 @param[out] ctx Pointer to context struct 160 **/ 161 PetscErrorCode BCDefinitionGetContext(BCDefinition bc_def, void *ctx) { 162 PetscFunctionBeginUser; 163 PetscAssertPointer(ctx, 2); 164 *(void **)ctx = bc_def->ctx; 165 PetscFunctionReturn(PETSC_SUCCESS); 166 } 167 168 /** 169 @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IFunction of boundary condition 170 171 @param[in,out] bc_def `BCDefinition` to add function pointers to 172 @param[in] create_qf Function to create `CeedQFunction` 173 @param[in] add_op Function to create and add `CeedOperator` to composite `CeedOperator` 174 **/ 175 PetscErrorCode BCDefinitionSetIFunction(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIFunctionOperator add_op) { 176 PetscFunctionBeginUser; 177 bc_def->CreateIFunctionQF = create_qf; 178 bc_def->AddIFunctionOperator = add_op; 179 PetscFunctionReturn(PETSC_SUCCESS); 180 } 181 182 /** 183 @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IJacobian of boundary condition 184 185 @param[in,out] bc_def `BCDefinition` to add function pointers to 186 @param[in] create_qf Function to create `CeedQFunction` 187 @param[in] add_op Function to create and add `CeedOperator` to composite `CeedOperator` 188 **/ 189 PetscErrorCode BCDefinitionSetIJacobian(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIJacobianOperator add_op) { 190 PetscFunctionBeginUser; 191 bc_def->CreateIJacobianQF = create_qf; 192 bc_def->AddIJacobianOperator = add_op; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 /** 197 @brief Add operators (IFunction, IJacobian) to composite operator 198 199 This loops over orientations for each face label specified by `bc_def` and adds the IFunction and IJacobian operator to respective composite operator. 200 201 @param[in] bc_def `BCDefinition` from which operators are created and added 202 @param[in,out] op_ifunc Composite operator for IFunction operators to be added to 203 @param[in,out] op_ijac Composite operator for IJacobian operators to be added to 204 **/ 205 PetscErrorCode BCDefinitionAddOperators(BCDefinition bc_def, CeedOperator op_ifunc, CeedOperator op_ijac) { 206 Ceed ceed = CeedOperatorReturnCeed(op_ifunc); 207 CeedQFunction qf_ifunction, qf_ijacobian; 208 DMLabel face_sets_label; 209 PetscInt num_face_set_values; 210 const PetscInt *face_set_values; 211 212 PetscFunctionBeginUser; 213 if (!bc_def->CreateIFunctionQF || !bc_def->AddIFunctionOperator) PetscFunctionReturn(PETSC_SUCCESS); 214 PetscBool add_ijac = (!bc_def->CreateIJacobianQF || !bc_def->AddIJacobianOperator) ? PETSC_FALSE : PETSC_TRUE; 215 PetscCheck(bc_def->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "BCDefinition must have DM set using BCDefinitionSetDM()"); 216 217 PetscCall(bc_def->CreateIFunctionQF(bc_def, &qf_ifunction)); 218 if (add_ijac) PetscCall(bc_def->CreateIJacobianQF(bc_def, &qf_ijacobian)); 219 220 PetscCall(DMGetLabel(bc_def->dm, "Face Sets", &face_sets_label)); 221 PetscCall(BCDefinitionGetInfo(bc_def, NULL, &num_face_set_values, &face_set_values)); 222 for (PetscInt f = 0; f < num_face_set_values; f++) { 223 DMLabel face_orientation_label; 224 PetscInt num_orientations_values, *orientation_values; 225 226 { 227 char *face_orientation_label_name; 228 229 PetscCall(DMPlexCreateFaceLabel(bc_def->dm, face_set_values[f], &face_orientation_label_name)); 230 PetscCall(DMGetLabel(bc_def->dm, face_orientation_label_name, &face_orientation_label)); 231 PetscCall(PetscFree(face_orientation_label_name)); 232 } 233 PetscCall(DMLabelCreateGlobalValueArray(bc_def->dm, face_orientation_label, &num_orientations_values, &orientation_values)); 234 for (PetscInt o = 0; o < num_orientations_values; o++) { 235 CeedOperator sub_op_ifunc; 236 PetscInt orientation = orientation_values[o]; 237 238 PetscCall(bc_def->AddIFunctionOperator(bc_def, face_orientation_label, orientation, qf_ifunction, op_ifunc, &sub_op_ifunc)); 239 if (add_ijac) PetscCall(bc_def->AddIJacobianOperator(bc_def, sub_op_ifunc, face_orientation_label, orientation, qf_ijacobian, op_ijac)); 240 PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ifunc)); 241 } 242 PetscCall(PetscFree(orientation_values)); 243 } 244 PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ifunction)); 245 if (add_ijac) PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ijacobian)); 246 PetscFunctionReturn(PETSC_SUCCESS); 247 PetscFunctionReturn(PETSC_SUCCESS); 248 } 249