xref: /honee/src/bc_definition.c (revision 96f347c2d98d5a49f1f235ee214da56e4c89681f)
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 
9*96f347c2SJames Wright PetscClassId BC_DEFINITION_CLASSID;
10*96f347c2SJames Wright 
11*96f347c2SJames Wright /**
12*96f347c2SJames Wright   @brief Initalize `BCDefinition` class.
13*96f347c2SJames Wright 
14*96f347c2SJames Wright   Not collective across MPI processes.
15*96f347c2SJames Wright 
16*96f347c2SJames Wright   @return An error code: 0 - success, otherwise - failure
17*96f347c2SJames Wright **/
18*96f347c2SJames Wright static PetscErrorCode BCDefinitionInitalize() {
19*96f347c2SJames Wright   static PetscBool registered = PETSC_FALSE;
20*96f347c2SJames Wright 
21*96f347c2SJames Wright   PetscFunctionBeginUser;
22*96f347c2SJames Wright   if (registered) PetscFunctionReturn(PETSC_SUCCESS);
23*96f347c2SJames Wright   PetscCall(PetscClassIdRegister("BCDefinition", &BC_DEFINITION_CLASSID));
24*96f347c2SJames Wright   registered = PETSC_TRUE;
25*96f347c2SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
26*96f347c2SJames Wright }
27*96f347c2SJames Wright 
28487a3b6eSJames Wright /**
29487a3b6eSJames Wright    @brief Create `BCDefinition`
30487a3b6eSJames Wright 
31*96f347c2SJames Wright    @param[in]  comm             `MPI_Comm` for the object
32487a3b6eSJames Wright    @param[in]  name             Name of the boundary condition
33487a3b6eSJames Wright    @param[in]  num_label_values Number of `DMLabel` values
34487a3b6eSJames Wright    @param[in]  label_values     Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values`
35487a3b6eSJames Wright    @param[out] bc_def           The new `BCDefinition`
36487a3b6eSJames Wright **/
37*96f347c2SJames Wright PetscErrorCode BCDefinitionCreate(MPI_Comm comm, const char *name, PetscInt num_label_values, PetscInt label_values[], BCDefinition *bc_def) {
38*96f347c2SJames Wright   BCDefinition bc_def_;
39487a3b6eSJames Wright 
40*96f347c2SJames Wright   PetscFunctionBeginUser;
41*96f347c2SJames Wright   PetscCall(BCDefinitionInitalize());
42*96f347c2SJames Wright   PetscCall(
43*96f347c2SJames Wright       PetscHeaderCreate(bc_def_, BC_DEFINITION_CLASSID, "BCDefinition", "BCDefinition", "BCDefinition", comm, BCDefinitionDestroy, BCDefinitionView));
44*96f347c2SJames Wright 
45*96f347c2SJames Wright   PetscCall(PetscStrallocpy(name, &bc_def_->name));
46*96f347c2SJames Wright   PetscCall(PetscObjectSetName((PetscObject)bc_def_, name));
47*96f347c2SJames Wright   bc_def_->num_label_values = num_label_values;
48*96f347c2SJames Wright   PetscCall(PetscMalloc1(num_label_values, &bc_def_->label_values));
49*96f347c2SJames Wright   for (PetscInt i = 0; i < num_label_values; i++) bc_def_->label_values[i] = label_values[i];
50*96f347c2SJames Wright   *bc_def = bc_def_;
51*96f347c2SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
52*96f347c2SJames Wright }
53*96f347c2SJames Wright 
54*96f347c2SJames Wright /**
55*96f347c2SJames Wright    @brief Destory a `BCDefinition` object
56*96f347c2SJames Wright 
57*96f347c2SJames Wright    @param[in,out] bc_def `BCDefinition` to be destroyed
58*96f347c2SJames Wright **/
59*96f347c2SJames Wright PetscErrorCode BCDefinitionDestroy(BCDefinition *bc_def) {
60*96f347c2SJames Wright   BCDefinition bc_def_ = *bc_def;
61*96f347c2SJames Wright   PetscFunctionBeginUser;
62*96f347c2SJames Wright   if (!bc_def_) PetscFunctionReturn(PETSC_SUCCESS);
63*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def_, BC_DEFINITION_CLASSID, 1);
64*96f347c2SJames Wright   if (bc_def_->name) PetscCall(PetscFree(bc_def_->name));
65*96f347c2SJames Wright   if (bc_def_->label_values) PetscCall(PetscFree(bc_def_->label_values));
66*96f347c2SJames Wright   if (bc_def_->essential_comps) PetscCall(PetscFree(bc_def_->essential_comps));
67*96f347c2SJames Wright   if (bc_def_->dm) PetscCall(DMDestroy(&bc_def_->dm));
68*96f347c2SJames Wright   if (bc_def_->DestroyCtx) PetscCall((*(bc_def_->DestroyCtx))(&bc_def_->ctx));
69*96f347c2SJames Wright   PetscCall(PetscHeaderDestroy(&bc_def_));
70*96f347c2SJames Wright   *bc_def = NULL;
71*96f347c2SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
72*96f347c2SJames Wright }
73*96f347c2SJames Wright 
74*96f347c2SJames Wright /**
75*96f347c2SJames Wright   @brief View a `BCDefinition` object.
76*96f347c2SJames Wright 
77*96f347c2SJames Wright   Not collective across MPI processes.
78*96f347c2SJames Wright 
79*96f347c2SJames Wright   @param[in]  bc_def  `BCDefinition` object
80*96f347c2SJames Wright   @param[in]  viewer     Optional `PetscViewer` context or `NULL`
81*96f347c2SJames Wright 
82*96f347c2SJames Wright   @return An error code: 0 - success, otherwise - failure
83*96f347c2SJames Wright **/
84*96f347c2SJames Wright PetscErrorCode BCDefinitionView(BCDefinition bc_def, PetscViewer viewer) {
85*96f347c2SJames Wright   PetscBool         is_ascii;
86*96f347c2SJames Wright   PetscViewerFormat format;
87*96f347c2SJames Wright   PetscMPIInt       size;
88*96f347c2SJames Wright 
89*96f347c2SJames Wright   PetscFunctionBeginUser;
90*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
91*96f347c2SJames Wright   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
92*96f347c2SJames Wright   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)bc_def), &viewer));
93*96f347c2SJames Wright 
94*96f347c2SJames Wright   PetscCall(PetscViewerGetFormat(viewer, &format));
95*96f347c2SJames Wright   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)bc_def), &size));
96*96f347c2SJames Wright   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
97*96f347c2SJames Wright 
98*96f347c2SJames Wright   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &is_ascii));
99*96f347c2SJames Wright   {
100*96f347c2SJames Wright     PetscBool is_detailed = format == PETSC_VIEWER_ASCII_INFO_DETAIL;
101*96f347c2SJames Wright 
102*96f347c2SJames Wright     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)bc_def, viewer));
103*96f347c2SJames Wright     PetscCall(PetscViewerASCIIPushTab(viewer));  // BCDefinition
104*96f347c2SJames Wright 
105*96f347c2SJames Wright     if (is_detailed) PetscCall(DMView(bc_def->dm, viewer));
106*96f347c2SJames Wright     PetscCall(PetscViewerASCIIPrintf(viewer, "DM Field: %" PetscInt_FMT "\n", bc_def->dm_field));
107*96f347c2SJames Wright     PetscCall(PetscViewerASCIIPrintf(viewer, "Face Sets:"));
108*96f347c2SJames Wright     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
109*96f347c2SJames Wright     if (bc_def->num_label_values > 0) {
110*96f347c2SJames Wright       for (PetscInt i = 0; i < bc_def->num_label_values; i++) {
111*96f347c2SJames Wright         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, bc_def->label_values[i]));
112*96f347c2SJames Wright       }
113*96f347c2SJames Wright       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
114*96f347c2SJames Wright     } else {
115*96f347c2SJames Wright       PetscCall(PetscViewerASCIIPrintf(viewer, " None\n"));
116*96f347c2SJames Wright     }
117*96f347c2SJames Wright     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
118*96f347c2SJames Wright 
119*96f347c2SJames Wright     PetscCall(PetscViewerASCIIPrintf(viewer, "Essential Components:"));
120*96f347c2SJames Wright     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
121*96f347c2SJames Wright     if (bc_def->num_essential_comps > 0) {
122*96f347c2SJames Wright       for (PetscInt i = 0; i < bc_def->num_essential_comps; i++) {
123*96f347c2SJames Wright         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, bc_def->essential_comps[i]));
124*96f347c2SJames Wright       }
125*96f347c2SJames Wright       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
126*96f347c2SJames Wright     } else {
127*96f347c2SJames Wright       PetscCall(PetscViewerASCIIPrintf(viewer, " None\n"));
128*96f347c2SJames Wright     }
129*96f347c2SJames Wright     PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
130*96f347c2SJames Wright 
131*96f347c2SJames Wright     PetscCall(PetscViewerASCIIPopTab(viewer));  // BCDefinition
132*96f347c2SJames Wright   }
133*96f347c2SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
134*96f347c2SJames Wright }
135*96f347c2SJames Wright 
136*96f347c2SJames Wright /**
137*96f347c2SJames Wright   @brief View `BCDefinition` from options database (command line/YAML)
138*96f347c2SJames Wright 
139*96f347c2SJames Wright   @param[in] bc_def `BCDefintion` to view
140*96f347c2SJames Wright   @param[in] obj    Optional object that provides the prefix for the options database (if `NULL` then the prefix in `bc_def` is used)
141*96f347c2SJames Wright   @param[in] name   Option string that is used to activate viewing
142*96f347c2SJames Wright **/
143*96f347c2SJames Wright PetscErrorCode BCDefinitionViewFromOptions(BCDefinition bc_def, PetscObject obj, const char name[]) {
144*96f347c2SJames Wright   PetscFunctionBegin;
145*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
146*96f347c2SJames Wright   PetscCall(PetscObjectViewFromOptions((PetscObject)bc_def, obj, name));
147487a3b6eSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
148487a3b6eSJames Wright }
149487a3b6eSJames Wright 
150487a3b6eSJames Wright /**
151487a3b6eSJames Wright    @brief Get base information for `BCDefinition`
152487a3b6eSJames Wright 
153487a3b6eSJames Wright    @param[in]  bc_def           `BCDefinition` to get information from
154487a3b6eSJames Wright    @param[out] name             Name of the `BCDefinition`
155487a3b6eSJames Wright    @param[out] num_label_values Number of `DMLabel` values
156487a3b6eSJames Wright    @param[out] label_values     Array of label values that define the boundaries controlled by the `BCDefinition`, size `num_label_values`
157487a3b6eSJames Wright **/
158487a3b6eSJames Wright PetscErrorCode BCDefinitionGetInfo(BCDefinition bc_def, const char *name[], PetscInt *num_label_values, const PetscInt *label_values[]) {
159487a3b6eSJames Wright   PetscFunctionBeginUser;
160*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
1610990a807SJames Wright   if (name) {
1620990a807SJames Wright     PetscAssertPointer(name, 2);
1630990a807SJames Wright     *name = bc_def->name;
1640990a807SJames Wright   }
165487a3b6eSJames Wright   if (label_values) {
1660990a807SJames Wright     PetscAssertPointer(num_label_values, 3);
1670990a807SJames Wright     PetscAssertPointer(label_values, 4);
168487a3b6eSJames Wright     *num_label_values = bc_def->num_label_values;
169487a3b6eSJames Wright     *label_values     = bc_def->label_values;
170487a3b6eSJames Wright   }
171487a3b6eSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
172487a3b6eSJames Wright }
173487a3b6eSJames Wright 
174487a3b6eSJames Wright /**
175487a3b6eSJames Wright    @brief Set `DM_BC_ESSENTIAL` boundary condition values
176487a3b6eSJames Wright 
177487a3b6eSJames Wright    @param[in,out] bc_def              `BCDefinition` to set values to
178487a3b6eSJames Wright    @param[in]     num_essential_comps Number of components to set
179487a3b6eSJames Wright    @param[in]     essential_comps     Array of components to set, size `num_essential_comps`
180487a3b6eSJames Wright **/
181487a3b6eSJames Wright PetscErrorCode BCDefinitionSetEssential(BCDefinition bc_def, PetscInt num_essential_comps, PetscInt essential_comps[]) {
182487a3b6eSJames Wright   PetscFunctionBeginUser;
183*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
184487a3b6eSJames Wright   bc_def->num_essential_comps = num_essential_comps;
185487a3b6eSJames Wright   PetscCall(PetscMalloc1(num_essential_comps, &bc_def->essential_comps));
186487a3b6eSJames Wright   PetscCall(PetscArraycpy(bc_def->essential_comps, essential_comps, num_essential_comps));
187487a3b6eSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
188487a3b6eSJames Wright }
189487a3b6eSJames Wright 
190487a3b6eSJames Wright /**
191487a3b6eSJames Wright    @brief Get `DM_BC_ESSENTIAL` boundary condition values
192487a3b6eSJames Wright 
193487a3b6eSJames Wright    @param[in]  bc_def              `BCDefinition` to set values to
194487a3b6eSJames Wright    @param[out] num_essential_comps Number of components to set
195487a3b6eSJames Wright    @param[out] essential_comps     Array of components to set, size `num_essential_comps`
196487a3b6eSJames Wright **/
197487a3b6eSJames Wright PetscErrorCode BCDefinitionGetEssential(BCDefinition bc_def, PetscInt *num_essential_comps, const PetscInt *essential_comps[]) {
198487a3b6eSJames Wright   PetscFunctionBeginUser;
199*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
2000990a807SJames Wright   PetscAssertPointer(num_essential_comps, 2);
2010990a807SJames Wright   PetscAssertPointer(essential_comps, 3);
202487a3b6eSJames Wright   *num_essential_comps = bc_def->num_essential_comps;
203487a3b6eSJames Wright   *essential_comps     = bc_def->essential_comps;
204487a3b6eSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
205487a3b6eSJames Wright }
206487a3b6eSJames Wright 
207487a3b6eSJames Wright #define LABEL_ARRAY_SIZE 256
208487a3b6eSJames Wright 
209487a3b6eSJames Wright // @brief See `PetscOptionsBCDefinition`
210ddf6e248SJames Wright PetscErrorCode PetscOptionsBCDefinition_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[],
211487a3b6eSJames Wright                                                 const char name[], BCDefinition *bc_def, PetscBool *set) {
212487a3b6eSJames Wright   PetscInt num_label_values = LABEL_ARRAY_SIZE, label_values[LABEL_ARRAY_SIZE] = {0};
213487a3b6eSJames Wright 
214487a3b6eSJames Wright   PetscFunctionBeginUser;
215487a3b6eSJames Wright   PetscCall(PetscOptionsIntArray(opt, text, man, label_values, &num_label_values, set));
216487a3b6eSJames Wright   if (num_label_values > 0) {
217*96f347c2SJames Wright     PetscCall(BCDefinitionCreate(PetscOptionsObject->comm, name, num_label_values, label_values, bc_def));
218487a3b6eSJames Wright   } else {
219487a3b6eSJames Wright     *bc_def = NULL;
220487a3b6eSJames Wright   }
221487a3b6eSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
222487a3b6eSJames Wright }
22309240e0aSJames Wright 
22409240e0aSJames Wright /**
22509240e0aSJames Wright   @brief Set `DM` for BCDefinition
22609240e0aSJames Wright 
22709240e0aSJames Wright   @param[in,out] bc_def `BCDefinition` to add `dm` to
22809240e0aSJames Wright   @param[in]     dm     `DM` to assign to BCDefinition, or `NULL` to remove `DM`
22909240e0aSJames Wright **/
23009240e0aSJames Wright PetscErrorCode BCDefinitionSetDM(BCDefinition bc_def, DM dm) {
23109240e0aSJames Wright   PetscFunctionBeginUser;
232*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
23309240e0aSJames Wright   if (bc_def->dm) PetscCall(DMDestroy(&bc_def->dm));
23409240e0aSJames Wright   if (dm) {
23509240e0aSJames Wright     PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
23609240e0aSJames Wright     PetscCall(PetscObjectReference((PetscObject)dm));
23709240e0aSJames Wright     bc_def->dm = dm;
23809240e0aSJames Wright   }
23909240e0aSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
24009240e0aSJames Wright }
24109240e0aSJames Wright 
24209240e0aSJames Wright /**
24309240e0aSJames Wright   @brief Get `DM` assigned to BCDefinition
24409240e0aSJames Wright 
24509240e0aSJames Wright   @param[in]  bc_def `BCDefinition` to get `dm` from
24609240e0aSJames Wright   @param[out] dm     `DM` assigned to BCDefinition
24709240e0aSJames Wright **/
24809240e0aSJames Wright PetscErrorCode BCDefinitionGetDM(BCDefinition bc_def, DM *dm) {
249*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
25009240e0aSJames Wright   PetscFunctionBeginUser;
25109240e0aSJames Wright   PetscAssertPointer(dm, 2);
25209240e0aSJames Wright   *dm = bc_def->dm;
25309240e0aSJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
25409240e0aSJames Wright }
2552e678684SJames Wright 
2562e678684SJames Wright /**
2572e678684SJames Wright   @brief Set custom context struct for use in BCDefinition
2582e678684SJames Wright 
2592e678684SJames Wright   @param[in,out] bc_def      `BCDefinition` to add `ctx` to
2602e678684SJames Wright   @param[in]     destroy_ctx Optional function pointer that destroys the user context on `BCDefinitionDestroy()`
2612e678684SJames Wright   @param[in]     ctx         Pointer to context struct
2622e678684SJames Wright **/
2632e678684SJames Wright PetscErrorCode BCDefinitionSetContext(BCDefinition bc_def, PetscCtxDestroyFn *destroy_ctx, void *ctx) {
2642e678684SJames Wright   PetscFunctionBeginUser;
265*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
2662e678684SJames Wright   if (bc_def->DestroyCtx) PetscCall((*(bc_def->DestroyCtx))(&bc_def->ctx));
2672e678684SJames Wright   bc_def->ctx        = ctx;
2682e678684SJames Wright   bc_def->DestroyCtx = destroy_ctx;
2692e678684SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
2702e678684SJames Wright }
2712e678684SJames Wright 
2722e678684SJames Wright /**
2732e678684SJames Wright   @brief Set custom context struct for use in BCDefinition
2742e678684SJames Wright 
2752e678684SJames Wright   @param[in]  bc_def `BCDefinition` to get `ctx` from
2762e678684SJames Wright   @param[out] ctx    Pointer to context struct
2772e678684SJames Wright **/
2782e678684SJames Wright PetscErrorCode BCDefinitionGetContext(BCDefinition bc_def, void *ctx) {
2792e678684SJames Wright   PetscFunctionBeginUser;
280*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
2812e678684SJames Wright   PetscAssertPointer(ctx, 2);
2822e678684SJames Wright   *(void **)ctx = bc_def->ctx;
2832e678684SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
2842e678684SJames Wright }
28577aa5ad7SJames Wright 
28677aa5ad7SJames Wright /**
28777aa5ad7SJames Wright   @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IFunction of boundary condition
28877aa5ad7SJames Wright 
28977aa5ad7SJames Wright   @param[in,out] bc_def    `BCDefinition` to add function pointers to
29077aa5ad7SJames Wright   @param[in]     create_qf Function to create `CeedQFunction`
29177aa5ad7SJames Wright   @param[in]     add_op    Function to create and add `CeedOperator` to composite `CeedOperator`
29277aa5ad7SJames Wright **/
29377aa5ad7SJames Wright PetscErrorCode BCDefinitionSetIFunction(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIFunctionOperator add_op) {
29477aa5ad7SJames Wright   PetscFunctionBeginUser;
295*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
29677aa5ad7SJames Wright   bc_def->CreateIFunctionQF    = create_qf;
29777aa5ad7SJames Wright   bc_def->AddIFunctionOperator = add_op;
29877aa5ad7SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
29977aa5ad7SJames Wright }
30077aa5ad7SJames Wright 
30177aa5ad7SJames Wright /**
30277aa5ad7SJames Wright   @brief Add function pointers to create `CeedQFunction` and `CeedOperator` for IJacobian of boundary condition
30377aa5ad7SJames Wright 
30477aa5ad7SJames Wright   @param[in,out] bc_def    `BCDefinition` to add function pointers to
30577aa5ad7SJames Wright   @param[in]     create_qf Function to create `CeedQFunction`
30677aa5ad7SJames Wright   @param[in]     add_op    Function to create and add `CeedOperator` to composite `CeedOperator`
30777aa5ad7SJames Wright **/
30877aa5ad7SJames Wright PetscErrorCode BCDefinitionSetIJacobian(BCDefinition bc_def, BCDefinitionCreateQFunction create_qf, BCDefinitionAddIJacobianOperator add_op) {
30977aa5ad7SJames Wright   PetscFunctionBeginUser;
310*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
31177aa5ad7SJames Wright   bc_def->CreateIJacobianQF    = create_qf;
31277aa5ad7SJames Wright   bc_def->AddIJacobianOperator = add_op;
31377aa5ad7SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
31477aa5ad7SJames Wright }
31577aa5ad7SJames Wright 
31677aa5ad7SJames Wright /**
31777aa5ad7SJames Wright   @brief Add operators (IFunction, IJacobian) to composite operator
31877aa5ad7SJames Wright 
31977aa5ad7SJames Wright   This loops over orientations for each face label specified by `bc_def` and adds the IFunction and IJacobian operator to respective composite operator.
32077aa5ad7SJames Wright 
32177aa5ad7SJames Wright   @param[in]     bc_def   `BCDefinition` from which operators are created and added
32277aa5ad7SJames Wright   @param[in,out] op_ifunc Composite operator for IFunction operators to be added to
32377aa5ad7SJames Wright   @param[in,out] op_ijac  Composite operator for IJacobian operators to be added to
32477aa5ad7SJames Wright **/
32577aa5ad7SJames Wright PetscErrorCode BCDefinitionAddOperators(BCDefinition bc_def, CeedOperator op_ifunc, CeedOperator op_ijac) {
32677aa5ad7SJames Wright   Ceed            ceed = CeedOperatorReturnCeed(op_ifunc);
32777aa5ad7SJames Wright   CeedQFunction   qf_ifunction, qf_ijacobian;
32877aa5ad7SJames Wright   DMLabel         face_sets_label;
32977aa5ad7SJames Wright   PetscInt        num_face_set_values;
33077aa5ad7SJames Wright   const PetscInt *face_set_values;
33177aa5ad7SJames Wright 
33277aa5ad7SJames Wright   PetscFunctionBeginUser;
333*96f347c2SJames Wright   PetscValidHeaderSpecific(bc_def, BC_DEFINITION_CLASSID, 1);
33477aa5ad7SJames Wright   if (!bc_def->CreateIFunctionQF || !bc_def->AddIFunctionOperator) PetscFunctionReturn(PETSC_SUCCESS);
335ea091b8eSJames Wright   PetscBool add_ijac = (!bc_def->CreateIJacobianQF || !bc_def->AddIJacobianOperator || !op_ijac) ? PETSC_FALSE : PETSC_TRUE;
33677aa5ad7SJames Wright   PetscCheck(bc_def->dm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "BCDefinition must have DM set using BCDefinitionSetDM()");
33777aa5ad7SJames Wright 
33877aa5ad7SJames Wright   PetscCall(bc_def->CreateIFunctionQF(bc_def, &qf_ifunction));
33977aa5ad7SJames Wright   if (add_ijac) PetscCall(bc_def->CreateIJacobianQF(bc_def, &qf_ijacobian));
34077aa5ad7SJames Wright 
34177aa5ad7SJames Wright   PetscCall(DMGetLabel(bc_def->dm, "Face Sets", &face_sets_label));
34277aa5ad7SJames Wright   PetscCall(BCDefinitionGetInfo(bc_def, NULL, &num_face_set_values, &face_set_values));
34377aa5ad7SJames Wright   for (PetscInt f = 0; f < num_face_set_values; f++) {
34477aa5ad7SJames Wright     DMLabel  face_orientation_label;
34577aa5ad7SJames Wright     PetscInt num_orientations_values, *orientation_values;
34677aa5ad7SJames Wright 
34777aa5ad7SJames Wright     {
34877aa5ad7SJames Wright       char *face_orientation_label_name;
34977aa5ad7SJames Wright 
35077aa5ad7SJames Wright       PetscCall(DMPlexCreateFaceLabel(bc_def->dm, face_set_values[f], &face_orientation_label_name));
35177aa5ad7SJames Wright       PetscCall(DMGetLabel(bc_def->dm, face_orientation_label_name, &face_orientation_label));
35277aa5ad7SJames Wright       PetscCall(PetscFree(face_orientation_label_name));
35377aa5ad7SJames Wright     }
35477aa5ad7SJames Wright     PetscCall(DMLabelCreateGlobalValueArray(bc_def->dm, face_orientation_label, &num_orientations_values, &orientation_values));
35577aa5ad7SJames Wright     for (PetscInt o = 0; o < num_orientations_values; o++) {
35677aa5ad7SJames Wright       CeedOperator sub_op_ifunc;
35777aa5ad7SJames Wright       PetscInt     orientation = orientation_values[o];
35877aa5ad7SJames Wright 
35977aa5ad7SJames Wright       PetscCall(bc_def->AddIFunctionOperator(bc_def, face_orientation_label, orientation, qf_ifunction, op_ifunc, &sub_op_ifunc));
36077aa5ad7SJames Wright       if (add_ijac) PetscCall(bc_def->AddIJacobianOperator(bc_def, sub_op_ifunc, face_orientation_label, orientation, qf_ijacobian, op_ijac));
36177aa5ad7SJames Wright       PetscCallCeed(ceed, CeedOperatorDestroy(&sub_op_ifunc));
36277aa5ad7SJames Wright     }
36377aa5ad7SJames Wright     PetscCall(PetscFree(orientation_values));
36477aa5ad7SJames Wright   }
36577aa5ad7SJames Wright   PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ifunction));
36677aa5ad7SJames Wright   if (add_ijac) PetscCallCeed(ceed, CeedQFunctionDestroy(&qf_ijacobian));
36777aa5ad7SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
36877aa5ad7SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
36977aa5ad7SJames Wright }
370