xref: /honee/src/bc_definition.c (revision ea091b8e43283667a8e2f5f647273e58272b0e63)
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