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