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