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 9487a3b6eSJames Wright /** 10487a3b6eSJames Wright @brief Create `BCDefinition` 11487a3b6eSJames Wright 12487a3b6eSJames Wright @param[in] name Name of the boundary condition 13487a3b6eSJames Wright @param[in] num_label_values Number of `DMLabel` values 14487a3b6eSJames Wright @param[in] label_values Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values` 15487a3b6eSJames Wright @param[out] bc_def The new `BCDefinition` 16487a3b6eSJames Wright **/ 17487a3b6eSJames Wright PetscErrorCode BCDefinitionCreate(const char *name, PetscInt num_label_values, PetscInt label_values[], BCDefinition *bc_def) { 18487a3b6eSJames Wright PetscFunctionBeginUser; 19487a3b6eSJames Wright PetscCall(PetscNew(bc_def)); 20487a3b6eSJames Wright 21487a3b6eSJames Wright PetscCall(PetscStrallocpy(name, &(*bc_def)->name)); 22487a3b6eSJames Wright (*bc_def)->num_label_values = num_label_values; 23487a3b6eSJames Wright PetscCall(PetscMalloc1(num_label_values, &(*bc_def)->label_values)); 24487a3b6eSJames Wright for (PetscInt i = 0; i < num_label_values; i++) (*bc_def)->label_values[i] = label_values[i]; 25487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 26487a3b6eSJames Wright } 27487a3b6eSJames Wright 28487a3b6eSJames Wright /** 29487a3b6eSJames Wright @brief Get base information for `BCDefinition` 30487a3b6eSJames Wright 31487a3b6eSJames Wright @param[in] bc_def `BCDefinition` to get information from 32487a3b6eSJames Wright @param[out] name Name of the `BCDefinition` 33487a3b6eSJames Wright @param[out] num_label_values Number of `DMLabel` values 34487a3b6eSJames Wright @param[out] label_values Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values` 35487a3b6eSJames Wright **/ 36487a3b6eSJames Wright PetscErrorCode BCDefinitionGetInfo(BCDefinition bc_def, const char *name[], PetscInt *num_label_values, const PetscInt *label_values[]) { 37487a3b6eSJames Wright PetscFunctionBeginUser; 380990a807SJames Wright if (name) { 390990a807SJames Wright PetscAssertPointer(name, 2); 400990a807SJames Wright *name = bc_def->name; 410990a807SJames Wright } 42487a3b6eSJames Wright if (label_values) { 430990a807SJames Wright PetscAssertPointer(num_label_values, 3); 440990a807SJames Wright PetscAssertPointer(label_values, 4); 45487a3b6eSJames Wright *num_label_values = bc_def->num_label_values; 46487a3b6eSJames Wright *label_values = bc_def->label_values; 47487a3b6eSJames Wright } 48487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 49487a3b6eSJames Wright } 50487a3b6eSJames Wright 51487a3b6eSJames Wright /** 52487a3b6eSJames Wright @brief Destory a `BCDefinition` object 53487a3b6eSJames Wright 54487a3b6eSJames Wright @param[in,out] bc_def `BCDefinition` to be destroyed 55487a3b6eSJames Wright **/ 56487a3b6eSJames Wright PetscErrorCode BCDefinitionDestroy(BCDefinition *bc_def) { 572e678684SJames Wright BCDefinition bc_def_ = *bc_def; 58487a3b6eSJames Wright PetscFunctionBeginUser; 592e678684SJames Wright if (bc_def_->name) PetscCall(PetscFree(bc_def_->name)); 602e678684SJames Wright if (bc_def_->label_values) PetscCall(PetscFree(bc_def_->label_values)); 612e678684SJames Wright if (bc_def_->essential_comps) PetscCall(PetscFree(bc_def_->essential_comps)); 622e678684SJames Wright if (bc_def_->dm) PetscCall(DMDestroy(&bc_def_->dm)); 632e678684SJames Wright if (bc_def_->DestroyCtx) PetscCall((*(bc_def_->DestroyCtx))(&bc_def_->ctx)); 642e678684SJames Wright PetscCall(PetscFree(bc_def_)); 65487a3b6eSJames Wright *bc_def = NULL; 66487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 67487a3b6eSJames Wright } 68487a3b6eSJames Wright 69487a3b6eSJames Wright /** 70487a3b6eSJames Wright @brief Set `DM_BC_ESSENTIAL` boundary condition values 71487a3b6eSJames Wright 72487a3b6eSJames Wright @param[in,out] bc_def `BCDefinition` to set values to 73487a3b6eSJames Wright @param[in] num_essential_comps Number of components to set 74487a3b6eSJames Wright @param[in] essential_comps Array of components to set, size `num_essential_comps` 75487a3b6eSJames Wright **/ 76487a3b6eSJames Wright PetscErrorCode BCDefinitionSetEssential(BCDefinition bc_def, PetscInt num_essential_comps, PetscInt essential_comps[]) { 77487a3b6eSJames Wright PetscFunctionBeginUser; 78487a3b6eSJames Wright bc_def->num_essential_comps = num_essential_comps; 79487a3b6eSJames Wright PetscCall(PetscMalloc1(num_essential_comps, &bc_def->essential_comps)); 80487a3b6eSJames Wright PetscCall(PetscArraycpy(bc_def->essential_comps, essential_comps, num_essential_comps)); 81487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 82487a3b6eSJames Wright } 83487a3b6eSJames Wright 84487a3b6eSJames Wright /** 85487a3b6eSJames Wright @brief Get `DM_BC_ESSENTIAL` boundary condition values 86487a3b6eSJames Wright 87487a3b6eSJames Wright @param[in] bc_def `BCDefinition` to set values to 88487a3b6eSJames Wright @param[out] num_essential_comps Number of components to set 89487a3b6eSJames Wright @param[out] essential_comps Array of components to set, size `num_essential_comps` 90487a3b6eSJames Wright **/ 91487a3b6eSJames Wright PetscErrorCode BCDefinitionGetEssential(BCDefinition bc_def, PetscInt *num_essential_comps, const PetscInt *essential_comps[]) { 92487a3b6eSJames Wright PetscFunctionBeginUser; 930990a807SJames Wright PetscAssertPointer(num_essential_comps, 2); 940990a807SJames Wright PetscAssertPointer(essential_comps, 3); 95487a3b6eSJames Wright *num_essential_comps = bc_def->num_essential_comps; 96487a3b6eSJames Wright *essential_comps = bc_def->essential_comps; 97487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 98487a3b6eSJames Wright } 99487a3b6eSJames Wright 100487a3b6eSJames Wright #define LABEL_ARRAY_SIZE 256 101487a3b6eSJames Wright 102487a3b6eSJames Wright // @brief See `PetscOptionsBCDefinition` 103ddf6e248SJames Wright PetscErrorCode PetscOptionsBCDefinition_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], 104487a3b6eSJames Wright const char name[], BCDefinition *bc_def, PetscBool *set) { 105487a3b6eSJames Wright PetscInt num_label_values = LABEL_ARRAY_SIZE, label_values[LABEL_ARRAY_SIZE] = {0}; 106487a3b6eSJames Wright 107487a3b6eSJames Wright PetscFunctionBeginUser; 108487a3b6eSJames Wright PetscCall(PetscOptionsIntArray(opt, text, man, label_values, &num_label_values, set)); 109487a3b6eSJames Wright if (num_label_values > 0) { 110487a3b6eSJames Wright PetscCall(BCDefinitionCreate(name, num_label_values, label_values, bc_def)); 111487a3b6eSJames Wright } else { 112487a3b6eSJames Wright *bc_def = NULL; 113487a3b6eSJames Wright } 114487a3b6eSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 115487a3b6eSJames Wright } 11609240e0aSJames Wright 11709240e0aSJames Wright /** 11809240e0aSJames Wright @brief Set `DM` for BCDefinition 11909240e0aSJames Wright 12009240e0aSJames Wright @param[in,out] bc_def `BCDefinition` to add `dm` to 12109240e0aSJames Wright @param[in] dm `DM` to assign to BCDefinition, or `NULL` to remove `DM` 12209240e0aSJames Wright **/ 12309240e0aSJames Wright PetscErrorCode BCDefinitionSetDM(BCDefinition bc_def, DM dm) { 12409240e0aSJames Wright PetscFunctionBeginUser; 12509240e0aSJames Wright if (bc_def->dm) PetscCall(DMDestroy(&bc_def->dm)); 12609240e0aSJames Wright if (dm) { 12709240e0aSJames Wright PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 12809240e0aSJames Wright PetscCall(PetscObjectReference((PetscObject)dm)); 12909240e0aSJames Wright bc_def->dm = dm; 13009240e0aSJames Wright } 13109240e0aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 13209240e0aSJames Wright } 13309240e0aSJames Wright 13409240e0aSJames Wright /** 13509240e0aSJames Wright @brief Get `DM` assigned to BCDefinition 13609240e0aSJames Wright 13709240e0aSJames Wright @param[in] bc_def `BCDefinition` to get `dm` from 13809240e0aSJames Wright @param[out] dm `DM` assigned to BCDefinition 13909240e0aSJames Wright **/ 14009240e0aSJames Wright PetscErrorCode BCDefinitionGetDM(BCDefinition bc_def, DM *dm) { 14109240e0aSJames Wright PetscFunctionBeginUser; 14209240e0aSJames Wright PetscAssertPointer(dm, 2); 14309240e0aSJames Wright *dm = bc_def->dm; 14409240e0aSJames Wright PetscFunctionReturn(PETSC_SUCCESS); 14509240e0aSJames Wright } 1462e678684SJames Wright 1472e678684SJames Wright /** 1482e678684SJames Wright @brief Set custom context struct for use in BCDefinition 1492e678684SJames Wright 1502e678684SJames Wright @param[in,out] bc_def `BCDefinition` to add `ctx` to 1512e678684SJames Wright @param[in] destroy_ctx Optional function pointer that destroys the user context on `BCDefinitionDestroy()` 1522e678684SJames Wright @param[in] ctx Pointer to context struct 1532e678684SJames Wright **/ 1542e678684SJames Wright PetscErrorCode BCDefinitionSetContext(BCDefinition bc_def, PetscCtxDestroyFn *destroy_ctx, void *ctx) { 1552e678684SJames Wright PetscFunctionBeginUser; 1562e678684SJames Wright if (bc_def->DestroyCtx) PetscCall((*(bc_def->DestroyCtx))(&bc_def->ctx)); 1572e678684SJames Wright bc_def->ctx = ctx; 1582e678684SJames Wright bc_def->DestroyCtx = destroy_ctx; 1592e678684SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1602e678684SJames Wright } 1612e678684SJames Wright 1622e678684SJames Wright /** 1632e678684SJames Wright @brief Set custom context struct for use in BCDefinition 1642e678684SJames Wright 1652e678684SJames Wright @param[in] bc_def `BCDefinition` to get `ctx` from 1662e678684SJames Wright @param[out] ctx Pointer to context struct 1672e678684SJames Wright **/ 1682e678684SJames Wright PetscErrorCode BCDefinitionGetContext(BCDefinition bc_def, void *ctx) { 1692e678684SJames Wright PetscFunctionBeginUser; 1702e678684SJames Wright PetscAssertPointer(ctx, 2); 1712e678684SJames Wright *(void **)ctx = bc_def->ctx; 1722e678684SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 1732e678684SJames Wright } 17477aa5ad7SJames Wright 17577aa5ad7SJames Wright /** 17677aa5ad7SJames Wright @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IFunction of boundary condition 17777aa5ad7SJames Wright 17877aa5ad7SJames Wright @param[in,out] bc_def `BCDefinition` to add function pointers to 17977aa5ad7SJames Wright @param[in] create_qf Function to create `CeedQFunction` 18077aa5ad7SJames Wright @param[in] add_op Function to create and add `CeedOperator` to composite `CeedOperator` 18177aa5ad7SJames Wright **/ 18277aa5ad7SJames Wright PetscErrorCode BCDefinitionSetIFunction(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIFunctionOperator add_op) { 18377aa5ad7SJames Wright PetscFunctionBeginUser; 18477aa5ad7SJames Wright bc_def->CreateIFunctionQF = create_qf; 18577aa5ad7SJames Wright bc_def->AddIFunctionOperator = add_op; 18677aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 18777aa5ad7SJames Wright } 18877aa5ad7SJames Wright 18977aa5ad7SJames Wright /** 19077aa5ad7SJames Wright @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IJacobian of boundary condition 19177aa5ad7SJames Wright 19277aa5ad7SJames Wright @param[in,out] bc_def `BCDefinition` to add function pointers to 19377aa5ad7SJames Wright @param[in] create_qf Function to create `CeedQFunction` 19477aa5ad7SJames Wright @param[in] add_op Function to create and add `CeedOperator` to composite `CeedOperator` 19577aa5ad7SJames Wright **/ 19677aa5ad7SJames Wright PetscErrorCode BCDefinitionSetIJacobian(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIJacobianOperator add_op) { 19777aa5ad7SJames Wright PetscFunctionBeginUser; 19877aa5ad7SJames Wright bc_def->CreateIJacobianQF = create_qf; 19977aa5ad7SJames Wright bc_def->AddIJacobianOperator = add_op; 20077aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 20177aa5ad7SJames Wright } 20277aa5ad7SJames Wright 20377aa5ad7SJames Wright /** 20477aa5ad7SJames Wright @brief Add operators (IFunction, IJacobian) to composite operator 20577aa5ad7SJames Wright 20677aa5ad7SJames Wright This loops over orientations for each face label specified by `bc_def` and adds the IFunction and IJacobian operator to respective composite operator. 20777aa5ad7SJames Wright 20877aa5ad7SJames Wright @param[in] bc_def `BCDefinition` from which operators are created and added 20977aa5ad7SJames Wright @param[in,out] op_ifunc Composite operator for IFunction operators to be added to 21077aa5ad7SJames Wright @param[in,out] op_ijac Composite operator for IJacobian operators to be added to 21177aa5ad7SJames Wright **/ 21277aa5ad7SJames Wright PetscErrorCode BCDefinitionAddOperators(BCDefinition bc_def, CeedOperator op_ifunc, CeedOperator op_ijac) { 21377aa5ad7SJames Wright Ceed ceed = CeedOperatorReturnCeed(op_ifunc); 21477aa5ad7SJames Wright CeedQFunction qf_ifunction, qf_ijacobian; 21577aa5ad7SJames Wright DMLabel face_sets_label; 21677aa5ad7SJames Wright PetscInt num_face_set_values; 21777aa5ad7SJames Wright const PetscInt *face_set_values; 21877aa5ad7SJames Wright 21977aa5ad7SJames Wright PetscFunctionBeginUser; 22077aa5ad7SJames Wright if (!bc_def->CreateIFunctionQF || !bc_def->AddIFunctionOperator) PetscFunctionReturn(PETSC_SUCCESS); 221*ea091b8eSJames Wright PetscBool add_ijac = (!bc_def->CreateIJacobianQF || !bc_def->AddIJacobianOperator || !op_ijac) ? PETSC_FALSE : PETSC_TRUE; 22277aa5ad7SJames Wright PetscCheck(bc_def->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "BCDefinition must have DM set using BCDefinitionSetDM()"); 22377aa5ad7SJames Wright 22477aa5ad7SJames Wright PetscCall(bc_def->CreateIFunctionQF(bc_def, &qf_ifunction)); 22577aa5ad7SJames Wright if (add_ijac) PetscCall(bc_def->CreateIJacobianQF(bc_def, &qf_ijacobian)); 22677aa5ad7SJames Wright 22777aa5ad7SJames Wright PetscCall(DMGetLabel(bc_def->dm, "Face Sets", &face_sets_label)); 22877aa5ad7SJames Wright PetscCall(BCDefinitionGetInfo(bc_def, NULL, &num_face_set_values, &face_set_values)); 22977aa5ad7SJames Wright for (PetscInt f = 0; f < num_face_set_values; f++) { 23077aa5ad7SJames Wright DMLabel face_orientation_label; 23177aa5ad7SJames Wright PetscInt num_orientations_values, *orientation_values; 23277aa5ad7SJames Wright 23377aa5ad7SJames Wright { 23477aa5ad7SJames Wright char *face_orientation_label_name; 23577aa5ad7SJames Wright 23677aa5ad7SJames Wright PetscCall(DMPlexCreateFaceLabel(bc_def->dm, face_set_values[f], &face_orientation_label_name)); 23777aa5ad7SJames Wright PetscCall(DMGetLabel(bc_def->dm, face_orientation_label_name, &face_orientation_label)); 23877aa5ad7SJames Wright PetscCall(PetscFree(face_orientation_label_name)); 23977aa5ad7SJames Wright } 24077aa5ad7SJames Wright PetscCall(DMLabelCreateGlobalValueArray(bc_def->dm, face_orientation_label, &num_orientations_values, &orientation_values)); 24177aa5ad7SJames Wright for (PetscInt o = 0; o < num_orientations_values; o++) { 24277aa5ad7SJames Wright CeedOperator sub_op_ifunc; 24377aa5ad7SJames Wright PetscInt orientation = orientation_values[o]; 24477aa5ad7SJames Wright 24577aa5ad7SJames Wright PetscCall(bc_def->AddIFunctionOperator(bc_def, face_orientation_label, orientation, qf_ifunction, op_ifunc, &sub_op_ifunc)); 24677aa5ad7SJames Wright if (add_ijac) PetscCall(bc_def->AddIJacobianOperator(bc_def, sub_op_ifunc, face_orientation_label, orientation, qf_ijacobian, op_ijac)); 24777aa5ad7SJames Wright PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ifunc)); 24877aa5ad7SJames Wright } 24977aa5ad7SJames Wright PetscCall(PetscFree(orientation_values)); 25077aa5ad7SJames Wright } 25177aa5ad7SJames Wright PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ifunction)); 25277aa5ad7SJames Wright if (add_ijac) PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ijacobian)); 25377aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 25477aa5ad7SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 25577aa5ad7SJames Wright } 256