Skip to content

Commit 14df4d5

Browse files
ChrisPsenicaChris Psenica
and
Chris Psenica
authoredMar 15, 2025··
wallDistanceMethod Flag Added To daOptions (#796)
* Adding wallDistanceMethod for daOption. Options are daCustom and default. This option is a flag for manually computing distance terms for CHT. I added a dedicated unit test for this (solid, incompressible, compressible) and removed it from previous unit tests. * There was a bug in the unit test where it was trying to switch to the directory it was already in. This has been fixed. * Fixing path for compressible unit test --------- Co-authored-by: Chris Psenica <cpsenica@Brahms.local>
1 parent b47e789 commit 14df4d5

10 files changed

+417
-65
lines changed
 

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ __pycache__
2828
reg_test_files*
2929
tests/*.txt
3030
tests/*.txt.orig
31+
.vscode/settings.json

‎dafoam/pyDAFoam.py

+3
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,9 @@ def __init__(self):
601601
# }
602602
}
603603

604+
## Whether to use OpenFOAMs snGrad() function or to manually compute distance for wall interfaces
605+
self.wallDistanceMethod = "default"
606+
604607

605608
class PYDAFOAM(object):
606609
"""

‎src/adjoint/DAFunction/DAFunctionWallHeatFlux.C

+14-31
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,14 @@ DAFunctionWallHeatFlux::DAFunctionWallHeatFlux(
4141
{
4242

4343
// check and assign values for scheme and formulation
44-
formMode_ = functionDict_.lookupOrDefault<word>("formulation", "default");
44+
distanceMode_ = daOption_.getAllOptions().getWord("wallDistanceMethod");
45+
if (distanceMode_ != "daCustom" && distanceMode_ != "default")
46+
{
47+
FatalErrorIn(" ") << "wallDistanceMethod: "
48+
<< distanceMode_ << " not supported!"
49+
<< " Options are: default and daCustom."
50+
<< abort(FatalError);
51+
}
4552
calcMode_ = functionDict_.lookupOrDefault<bool>("byUnitArea", true);
4653

4754
if (mesh_.thisDb().foundObject<DATurbulenceModel>("DATurbulenceModel"))
@@ -146,12 +153,12 @@ scalar DAFunctionWallHeatFlux::calcFunction()
146153
if (!wallHeatFluxBf[patchI].coupled())
147154
{
148155
// use OpenFOAM's snGrad()
149-
if (formMode_ == "default")
156+
if (distanceMode_ == "default")
150157
{
151158
wallHeatFluxBf[patchI] = Cp_ * alphaEffBf[patchI] * TBf[patchI].snGrad();
152159
}
153160
// use DAFOAM's custom formulation
154-
else if (formMode_ == "daCustom")
161+
else if (distanceMode_ == "daCustom")
155162
{
156163
forAll(wallHeatFluxBf[patchI], faceI)
157164
{
@@ -165,14 +172,6 @@ scalar DAFunctionWallHeatFlux::calcFunction()
165172
wallHeatFluxBf[patchI][faceI] = Cp_ * alphaEffBf[patchI][faceI] * dTdz;
166173
}
167174
}
168-
// error message incase of invalid entry
169-
else
170-
{
171-
FatalErrorIn(" ") << "formulation: "
172-
<< formMode_ << " not supported!"
173-
<< " Options are: default and daCustom."
174-
<< abort(FatalError);
175-
}
176175
}
177176
}
178177
}
@@ -191,12 +190,12 @@ scalar DAFunctionWallHeatFlux::calcFunction()
191190
if (!wallHeatFluxBf[patchI].coupled())
192191
{
193192
// use OpenFOAM's snGrad()
194-
if (formMode_ == "default")
193+
if (distanceMode_ == "default")
195194
{
196195
wallHeatFluxBf[patchI] = alphaEffBf[patchI] * heBf[patchI].snGrad();
197196
}
198197
// use DAFOAM's custom formulation
199-
else if (formMode_ == "daCustom")
198+
else if (distanceMode_ == "daCustom")
200199
{
201200
forAll(wallHeatFluxBf[patchI], faceI)
202201
{
@@ -210,14 +209,6 @@ scalar DAFunctionWallHeatFlux::calcFunction()
210209
wallHeatFluxBf[patchI][faceI] = alphaEffBf[patchI][faceI] * dHedz;
211210
}
212211
}
213-
// error message incase of invalid entry
214-
else
215-
{
216-
FatalErrorIn(" ") << "formulation: "
217-
<< formMode_ << " not supported!"
218-
<< " Options are: default and daCustom."
219-
<< abort(FatalError);
220-
}
221212
}
222213
}
223214
}
@@ -236,12 +227,12 @@ scalar DAFunctionWallHeatFlux::calcFunction()
236227
{
237228

238229
// use OpenFOAM's snGrad()
239-
if (formMode_ == "default")
230+
if (distanceMode_ == "default")
240231
{
241232
wallHeatFluxBf[patchI] = k_ * TBf[patchI].snGrad();
242233
}
243234
// use DAFOAM's custom formulation
244-
else if (formMode_ == "daCustom")
235+
else if (distanceMode_ == "daCustom")
245236
{
246237
forAll(wallHeatFluxBf[patchI], faceI)
247238
{
@@ -255,14 +246,6 @@ scalar DAFunctionWallHeatFlux::calcFunction()
255246
wallHeatFluxBf[patchI][faceI] = k_ * dTdz;
256247
}
257248
}
258-
// error message incase of invalid entry
259-
else
260-
{
261-
FatalErrorIn(" ") << "formulation: "
262-
<< formMode_ << " not supported!"
263-
<< " Options are: default and daCustom."
264-
<< abort(FatalError);
265-
}
266249
}
267250
}
268251
}

‎src/adjoint/DAFunction/DAFunctionWallHeatFlux.H

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ protected:
4444
bool calcMode_;
4545

4646
/// if calculating wallHeatFlux by OpenFOAMs snGrad() or DAFOAM's custom (daCustom) formulation
47-
word formMode_;
47+
word distanceMode_;
4848

4949
public:
5050
TypeName("wallHeatFlux");

‎src/adjoint/DAInput/DAInputThermalCoupling.C

+52-9
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,19 @@ DAInputThermalCoupling::DAInputThermalCoupling(
3636
// NOTE: always sort the patch because the order of the patch element matters in CHT coupling
3737
sort(patches_);
3838

39+
// check discipline
3940
discipline_ = daOption_.getAllOptions().getWord("discipline");
4041

42+
// check coupling mode and validate
43+
distanceMode_ = daOption_.getAllOptions().getWord("wallDistanceMethod");
44+
if (distanceMode_ != "daCustom" && distanceMode_ != "default")
45+
{
46+
FatalErrorIn(" ") << "wallDistanceMethod: "
47+
<< distanceMode_ << " not supported!"
48+
<< " Options are: default and daCustom."
49+
<< abort(FatalError);
50+
}
51+
4152
size_ = 0;
4253
forAll(patches_, idxI)
4354
{
@@ -83,6 +94,7 @@ void DAInputThermalCoupling::run(const scalarList& input)
8394

8495
// ********* second loop, set the valueFraction:
8596
// neighKDeltaCoeffs / ( neighKDeltaCoeffs + myKDeltaCoeffs)
97+
scalar deltaCoeffs = 0;
8698

8799
if (discipline_ == "aero")
88100
{
@@ -116,8 +128,19 @@ void DAInputThermalCoupling::run(const scalarList& input)
116128

117129
forAll(mesh_.boundaryMesh()[patchI], faceI)
118130
{
119-
// deltaCoeffs = 1 / d
120-
scalar deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
131+
if (distanceMode_ == "default")
132+
{
133+
// deltaCoeffs = 1 / d
134+
deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
135+
}
136+
else if (distanceMode_ == "daCustom")
137+
{
138+
label nearWallCellIndex = mesh_.boundaryMesh()[patchI].faceCells()[faceI];
139+
vector c1 = mesh_.Cf().boundaryField()[patchI][faceI];
140+
vector c2 = mesh_.C()[nearWallCellIndex];
141+
scalar d = mag(c1 - c2);
142+
deltaCoeffs = 1 / d;
143+
}
121144
scalar alphaEffBf = alphaEff.boundaryField()[patchI][faceI];
122145
scalar myKDeltaCoeffs = Cp * alphaEffBf * deltaCoeffs;
123146
// NOTE: we continue to use the counterI from the first loop
@@ -175,8 +198,19 @@ void DAInputThermalCoupling::run(const scalarList& input)
175198

176199
forAll(mesh_.boundaryMesh()[patchI], faceI)
177200
{
178-
// deltaCoeffs = 1 / d
179-
scalar deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
201+
if (distanceMode_ == "default")
202+
{
203+
// deltaCoeffs = 1 / d
204+
deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
205+
}
206+
else if (distanceMode_ == "daCustom")
207+
{
208+
label nearWallCellIndex = mesh_.boundaryMesh()[patchI].faceCells()[faceI];
209+
vector c1 = mesh_.Cf().boundaryField()[patchI][faceI];
210+
vector c2 = mesh_.C()[nearWallCellIndex];
211+
scalar d = mag(c1 - c2);
212+
deltaCoeffs = 1 / d;
213+
}
180214
scalar alphaEffBf = alphaEff.boundaryField()[patchI][faceI];
181215
scalar myKDeltaCoeffs = tmpVal * alphaEffBf * deltaCoeffs;
182216
// NOTE: we continue to use the counterI from the first loop
@@ -206,13 +240,22 @@ void DAInputThermalCoupling::run(const scalarList& input)
206240
word patchName = patches_[idxI];
207241
label patchI = mesh_.boundaryMesh().findPatchID(patchName);
208242

209-
mixedFvPatchField<scalar>& mixedPatch =
210-
refCast<mixedFvPatchField<scalar>>(T.boundaryFieldRef()[patchI]);
211-
212243
forAll(mesh_.boundaryMesh()[patchI], faceI)
213244
{
214-
// deltaCoeffs = 1 / d
215-
scalar deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
245+
if (distanceMode_ == "default")
246+
{
247+
// deltaCoeffs = 1 / d
248+
deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
249+
}
250+
else if (distanceMode_ == "daCustom")
251+
{
252+
label nearWallCellIndex = mesh_.boundaryMesh()[patchI].faceCells()[faceI];
253+
vector c1 = mesh_.Cf().boundaryField()[patchI][faceI];
254+
vector c2 = mesh_.C()[nearWallCellIndex];
255+
scalar d = mag(c1 - c2);
256+
deltaCoeffs = 1 / d;
257+
}
258+
mixedFvPatchField<scalar>& mixedPatch = refCast<mixedFvPatchField<scalar>>(T.boundaryFieldRef()[patchI]);
216259
scalar myKDeltaCoeffs = k * deltaCoeffs;
217260
// NOTE: we continue to use the counterI from the first loop
218261
scalar neighKDeltaCoeffs = input[counterI];

‎src/adjoint/DAInput/DAInputThermalCoupling.H

+3
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ protected:
5555
/// whether this is flow or solid
5656
word discipline_;
5757

58+
/// if calculating wallHeatFlux by OpenFOAMs snGrad() or DAFOAM's custom (daCustom) formulation
59+
word distanceMode_;
60+
5861
public:
5962
TypeName("thermalCouplingInput");
6063
// Constructors

‎src/adjoint/DAOutput/DAOutputThermalCoupling.C

100644100755
+51-6
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,19 @@ DAOutputThermalCoupling::DAOutputThermalCoupling(
3939
// NOTE: always sort the patch because the order of the patch element matters in CHT coupling
4040
sort(patches_);
4141

42+
// check discipline
4243
discipline_ = daOption_.getAllOptions().getWord("discipline");
4344

45+
// check coupling mode and validate
46+
distanceMode_ = daOption_.getAllOptions().getWord("wallDistanceMethod");
47+
if (distanceMode_ != "daCustom" && distanceMode_ != "default")
48+
{
49+
FatalErrorIn(" ") << "wallDistanceMethod: "
50+
<< distanceMode_ << " not supported!"
51+
<< " Options are: default and daCustom."
52+
<< abort(FatalError);
53+
}
54+
4455
size_ = 0;
4556
forAll(patches_, idxI)
4657
{
@@ -81,6 +92,7 @@ void DAOutputThermalCoupling::run(scalarList& output)
8192
}
8293

8394
// ********* second loop, get the (kappa / d) coefficient
95+
scalar deltaCoeffs = 0;
8496

8597
if (discipline_ == "aero")
8698
{
@@ -111,8 +123,19 @@ void DAOutputThermalCoupling::run(scalarList& output)
111123
label patchI = mesh_.boundaryMesh().findPatchID(patchName);
112124
forAll(mesh_.boundaryMesh()[patchI], faceI)
113125
{
114-
// deltaCoeffs = 1 / d
115-
scalar deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
126+
if (distanceMode_ == "default")
127+
{
128+
// deltaCoeffs = 1 / d
129+
deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
130+
}
131+
else if (distanceMode_ == "daCustom")
132+
{
133+
label nearWallCellIndex = mesh_.boundaryMesh()[patchI].faceCells()[faceI];
134+
vector c1 = mesh_.Cf().boundaryField()[patchI][faceI];
135+
vector c2 = mesh_.C()[nearWallCellIndex];
136+
scalar d = mag(c1 - c2);
137+
deltaCoeffs = 1 / d;
138+
}
116139
scalar alphaEffBf = alphaEff.boundaryField()[patchI][faceI];
117140
// NOTE: we continue to use the counterI from the first loop
118141
output[counterI] = Cp * alphaEffBf * deltaCoeffs;
@@ -165,8 +188,19 @@ void DAOutputThermalCoupling::run(scalarList& output)
165188
label patchI = mesh_.boundaryMesh().findPatchID(patchName);
166189
forAll(mesh_.boundaryMesh()[patchI], faceI)
167190
{
168-
// deltaCoeffs = 1 / d
169-
scalar deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
191+
if (distanceMode_ == "default")
192+
{
193+
// deltaCoeffs = 1 / d
194+
deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
195+
}
196+
else if (distanceMode_ == "daCustom")
197+
{
198+
label nearWallCellIndex = mesh_.boundaryMesh()[patchI].faceCells()[faceI];
199+
vector c1 = mesh_.Cf().boundaryField()[patchI][faceI];
200+
vector c2 = mesh_.C()[nearWallCellIndex];
201+
scalar d = mag(c1 - c2);
202+
deltaCoeffs = 1 / d;
203+
}
170204
scalar alphaEffBf = alphaEff.boundaryField()[patchI][faceI];
171205
// NOTE: we continue to use the counterI from the first loop
172206
output[counterI] = tmpVal * alphaEffBf * deltaCoeffs;
@@ -195,8 +229,19 @@ void DAOutputThermalCoupling::run(scalarList& output)
195229
label patchI = mesh_.boundaryMesh().findPatchID(patchName);
196230
forAll(mesh_.boundaryMesh()[patchI], faceI)
197231
{
198-
// deltaCoeffs = 1 / d
199-
scalar deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
232+
if (distanceMode_ == "default")
233+
{
234+
// deltaCoeffs = 1 / d
235+
deltaCoeffs = T.boundaryField()[patchI].patch().deltaCoeffs()[faceI];
236+
}
237+
else if (distanceMode_ == "daCustom")
238+
{
239+
label nearWallCellIndex = mesh_.boundaryMesh()[patchI].faceCells()[faceI];
240+
vector c1 = mesh_.Cf().boundaryField()[patchI][faceI];
241+
vector c2 = mesh_.C()[nearWallCellIndex];
242+
scalar d = mag(c1 - c2);
243+
deltaCoeffs = 1 / d;
244+
}
200245
// NOTE: we continue to use the counterI from the first loop
201246
output[counterI] = k * deltaCoeffs;
202247
counterI++;

‎src/adjoint/DAOutput/DAOutputThermalCoupling.H

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ protected:
5151
/// whether this is flow or solid
5252
word discipline_;
5353

54+
/// if calculating wallHeatFlux by OpenFOAMs snGrad() or DAFOAM's custom (daCustom) formulation
55+
word distanceMode_;
56+
5457
public:
5558
TypeName("thermalCouplingOutput");
5659
// Constructors

‎tests/runUnitTests_DACustomCHT.py

+289
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
#!/usr/bin/env python
2+
"""
3+
Run Python tests for optimization integration
4+
"""
5+
6+
import openmdao.api as om
7+
import os
8+
import numpy as np
9+
10+
from mpi4py import MPI
11+
from dafoam import PYDAFOAM
12+
from testFuncs import *
13+
from mphys.multipoint import Multipoint
14+
from dafoam.mphys import DAFoamBuilder
15+
from funtofem.mphys import MeldThermalBuilder
16+
from pygeo import geo_utils
17+
from mphys.scenario_aerothermal import ScenarioAeroThermal
18+
from pygeo.mphys import OM_DVGEOCOMP
19+
20+
# NOTE: we will test DASimpleFoam and DAHeatTransferFoam for incompressible, compressible, and solid solvers using the daCustom wallDistanceMethod
21+
22+
# ********************
23+
# incompressible tests
24+
# ********************
25+
gcomm = MPI.COMM_WORLD
26+
os.chdir("./reg_test_files-main/ChannelConjugateHeatV4")
27+
28+
if gcomm.rank == 0:
29+
os.system("rm -rf */processor*")
30+
31+
# aero setup
32+
U0 = 10.0
33+
34+
daOptionsAero = {
35+
"designSurfaces": [
36+
"hot_air_inner",
37+
"hot_air_outer",
38+
"hot_air_sides",
39+
"cold_air_outer",
40+
"cold_air_inner",
41+
"cold_air_sides",
42+
],
43+
"solverName": "DASimpleFoam",
44+
"wallDistanceMethod": "daCustom",
45+
"primalMinResTol": 1.0e-12,
46+
"primalMinResTolDiff": 1.0e12,
47+
"discipline": "aero",
48+
"primalBC": {
49+
"UHot": {"variable": "U", "patches": ["hot_air_in"], "value": [U0, 0.0, 0.0]},
50+
"UCold": {"variable": "U", "patches": ["cold_air_in"], "value": [-U0, 0.0, 0.0]},
51+
"useWallFunction": False,
52+
},
53+
"function": {
54+
"HFX": {
55+
"type": "wallHeatFlux",
56+
"byUnitArea": False,
57+
"source": "patchToFace",
58+
"patches": ["hot_air_inner"],
59+
"scale": 1,
60+
},
61+
},
62+
"adjStateOrdering": "cell",
63+
"adjEqnOption": {
64+
"gmresRelTol": 1.0e-3,
65+
"pcFillLevel": 1,
66+
"jacMatReOrdering": "natural",
67+
"useNonZeroInitGuess": True,
68+
"dynAdjustTol": True,
69+
},
70+
"normalizeStates": {
71+
"U": U0,
72+
"p": U0 * U0 / 2.0,
73+
"nuTilda": 1e-3,
74+
"T": 300,
75+
"phi": 1.0,
76+
},
77+
"inputInfo": {
78+
"aero_vol_coords": {"type": "volCoord", "components": ["solver", "function"]},
79+
"T_convect": {
80+
"type": "thermalCouplingInput",
81+
"patches": ["hot_air_inner", "cold_air_outer"],
82+
"components": ["solver"],
83+
},
84+
},
85+
"outputInfo": {
86+
"q_convect": {
87+
"type": "thermalCouplingOutput",
88+
"patches": ["hot_air_inner", "cold_air_outer"],
89+
"components": ["thermalCoupling"],
90+
},
91+
},
92+
}
93+
94+
daOptionsThermal = {
95+
"designSurfaces": ["channel_outer", "channel_inner", "channel_sides"],
96+
"solverName": "DAHeatTransferFoam",
97+
"wallDistanceMethod": "daCustom",
98+
"primalMinResTol": 1.0e-12,
99+
"primalMinResTolDiff": 1.0e12,
100+
"discipline": "thermal",
101+
"function": {
102+
"HF_INNER": {
103+
"type": "wallHeatFlux",
104+
"byUnitArea": False,
105+
"source": "patchToFace",
106+
"patches": ["channel_inner"],
107+
"scale": 1,
108+
},
109+
},
110+
"adjStateOrdering": "cell",
111+
"adjEqnOption": {
112+
"gmresRelTol": 1.0e-3,
113+
"pcFillLevel": 1,
114+
"jacMatReOrdering": "natural",
115+
"useNonZeroInitGuess": True,
116+
"dynAdjustTol": True,
117+
},
118+
"normalizeStates": {
119+
"T": 300.0,
120+
},
121+
"inputInfo": {
122+
"thermal_vol_coords": {"type": "volCoord", "components": ["solver", "function"]},
123+
"q_conduct": {
124+
"type": "thermalCouplingInput",
125+
"patches": ["channel_outer", "channel_inner"],
126+
"components": ["solver"],
127+
},
128+
},
129+
"outputInfo": {
130+
"T_conduct": {
131+
"type": "thermalCouplingOutput",
132+
"patches": ["channel_outer", "channel_inner"],
133+
"components": ["thermalCoupling"],
134+
},
135+
},
136+
}
137+
138+
# Mesh deformation setup
139+
meshOptions = {
140+
"gridFile": os.getcwd(),
141+
"fileType": "OpenFOAM",
142+
# point and normal for the symmetry plane
143+
"symmetryPlanes": [],
144+
}
145+
146+
147+
class Top(Multipoint):
148+
def setup(self):
149+
150+
dafoam_builder_aero = DAFoamBuilder(daOptionsAero, meshOptions, scenario="aerothermal", run_directory="aero")
151+
dafoam_builder_aero.initialize(self.comm)
152+
153+
dafoam_builder_thermal = DAFoamBuilder(
154+
daOptionsThermal, meshOptions, scenario="aerothermal", run_directory="thermal"
155+
)
156+
dafoam_builder_thermal.initialize(self.comm)
157+
158+
thermalxfer_builder = MeldThermalBuilder(dafoam_builder_aero, dafoam_builder_thermal, n=1, beta=0.5)
159+
thermalxfer_builder.initialize(self.comm)
160+
161+
# add the design variable component to keep the top level design variables
162+
self.add_subsystem("dvs", om.IndepVarComp(), promotes=["*"])
163+
164+
# add the mesh component
165+
self.add_subsystem("mesh_aero", dafoam_builder_aero.get_mesh_coordinate_subsystem())
166+
self.add_subsystem("mesh_thermal", dafoam_builder_thermal.get_mesh_coordinate_subsystem())
167+
168+
# add the geometry component (FFD). Note that the aero and thermal use the exact same FFD file
169+
self.add_subsystem("geometry_aero", OM_DVGEOCOMP(file="aero/FFD/channelFFD.xyz", type="ffd"))
170+
self.add_subsystem("geometry_thermal", OM_DVGEOCOMP(file="aero/FFD/channelFFD.xyz", type="ffd"))
171+
172+
# add a scenario (flow condition) for optimization, we pass the builder
173+
# to the scenario to actually run the flow and adjoint
174+
self.mphys_add_scenario(
175+
"scenario",
176+
ScenarioAeroThermal(
177+
aero_builder=dafoam_builder_aero,
178+
thermal_builder=dafoam_builder_thermal,
179+
thermalxfer_builder=thermalxfer_builder,
180+
),
181+
om.NonlinearBlockGS(maxiter=20, iprint=2, use_aitken=True, rtol=1e-8, atol=1e-14),
182+
om.LinearBlockGS(maxiter=20, iprint=2, use_aitken=True, rtol=1e-8, atol=1e-14),
183+
)
184+
185+
# need to manually connect the x_aero0 between the mesh and geometry components
186+
self.connect("mesh_aero.x_aero0", "geometry_aero.x_aero_in")
187+
self.connect("geometry_aero.x_aero0", "scenario.x_aero")
188+
189+
self.connect("mesh_thermal.x_thermal0", "geometry_thermal.x_thermal_in")
190+
self.connect("geometry_thermal.x_thermal0", "scenario.x_thermal")
191+
192+
def configure(self):
193+
194+
super().configure()
195+
196+
# get the surface coordinates from the mesh component
197+
points_aero = self.mesh_aero.mphys_get_surface_mesh()
198+
points_thermal = self.mesh_thermal.mphys_get_surface_mesh()
199+
200+
# add pointset to the geometry component
201+
self.geometry_aero.nom_add_discipline_coords("aero", points_aero)
202+
self.geometry_thermal.nom_add_discipline_coords("thermal", points_thermal)
203+
204+
# geometry setup
205+
pts = self.geometry_aero.DVGeo.getLocalIndex(0)
206+
dir_y = np.array([0.0, 1.0, 0.0])
207+
shapes = []
208+
shapes.append({pts[9, 0, 0]: dir_y, pts[9, 0, 1]: dir_y})
209+
self.geometry_aero.nom_addShapeFunctionDV(dvName="shape", shapes=shapes)
210+
self.geometry_thermal.nom_addShapeFunctionDV(dvName="shape", shapes=shapes)
211+
212+
# add the design variables to the dvs component's output
213+
self.dvs.add_output("shape", val=np.array([0]))
214+
# manually connect the dvs output to the geometry
215+
self.connect("shape", "geometry_aero.shape")
216+
self.connect("shape", "geometry_thermal.shape")
217+
218+
# define the design variables to the top level
219+
self.add_design_var("shape", lower=-1, upper=1, scaler=1.0)
220+
221+
# add objective and constraints to the top level
222+
self.add_objective("scenario.aero_post.HFX", scaler=1.0)
223+
224+
225+
prob = om.Problem()
226+
prob.model = Top()
227+
228+
prob.setup(mode="rev")
229+
prob.run_model()
230+
231+
HFX = prob.get_val("scenario.aero_post.HFX")[0]
232+
print("HFX:", HFX)
233+
if (abs(HFX - 180000.0) / (HFX + 1e-16)) > 1e-6:
234+
print("DAHeatTransferFoam test failed for DACustomCHT!")
235+
exit(1)
236+
else:
237+
print("DAHeatTransferFoam test passed for DACustomCHT!")
238+
239+
240+
# ********************
241+
# compressible tests
242+
# ********************
243+
os.chdir("../ConvergentChannel")
244+
if gcomm.rank == 0:
245+
os.system("rm -rf 0/* processor* *.bin")
246+
os.system("cp -r 0.compressible/* 0/")
247+
os.system("cp -r system.subsonic/* system/")
248+
os.system("cp -r constant/turbulenceProperties.sa constant/turbulenceProperties")
249+
250+
# aero setup
251+
U0 = 100.0
252+
253+
daOptions = {
254+
"solverName": "DARhoSimpleFoam",
255+
"wallDistanceMethod": "daCustom",
256+
"primalMinResTol": 1.0e-12,
257+
"primalMinResTolDiff": 1e4,
258+
"printDAOptions": False,
259+
"primalBC": {
260+
"U0": {"variable": "U", "patches": ["inlet"], "value": [U0, 0.0, 0.0]},
261+
"T0": {"variable": "T", "patches": ["inlet"], "value": [310.0]},
262+
"p0": {"variable": "p", "patches": ["outlet"], "value": [101325.0]},
263+
"useWallFunction": True,
264+
},
265+
"function": {
266+
"HFX": {
267+
"type": "wallHeatFlux",
268+
"byUnitArea": False,
269+
"source": "patchToFace",
270+
"patches": ["walls"],
271+
"scale": 1.0,
272+
},
273+
},
274+
}
275+
276+
DASolver = PYDAFOAM(options=daOptions, comm=gcomm)
277+
DASolver()
278+
279+
funcs = {}
280+
DASolver.evalFunctions(funcs)
281+
282+
diff = abs(8967.626339018574 - funcs["HFX"]) / 8967.626339018574
283+
if diff > 1e-10:
284+
if gcomm.rank == 0:
285+
print("DAFunction comp test failed for DACustomCHT")
286+
exit(1)
287+
else:
288+
if gcomm.rank == 0:
289+
print("DAFunction comp test passed for DACustomCHT!")

‎tests/runUnitTests_DAFunction.py

-18
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,6 @@
6565
"patches": ["walls"],
6666
"scale": 1.0,
6767
},
68-
"HFX_custom": {
69-
"type": "wallHeatFlux",
70-
"byUnitArea": False,
71-
"formulation": "daCustom",
72-
"source": "patchToFace",
73-
"patches": ["walls"],
74-
"scale": 1.0,
75-
},
7668
"PMean": {
7769
"type": "patchMean",
7870
"source": "patchToFace",
@@ -234,7 +226,6 @@
234226
"CMZ": 7.1768354637131795,
235227
"TP1": 2.5561992647012914,
236228
"HFX": 8.20332195479527,
237-
"HFX_custom": 28.645216245520146,
238229
"PMean": 77.80996323506456,
239230
"UMean": 15.469850053816028,
240231
"skewness": 1.3140396235456926,
@@ -299,14 +290,6 @@
299290
"patches": ["walls"],
300291
"scale": 1.0,
301292
},
302-
"HFX_custom": {
303-
"type": "wallHeatFlux",
304-
"byUnitArea": False,
305-
"formulation": "daCustom",
306-
"source": "patchToFace",
307-
"patches": ["walls"],
308-
"scale": 1.0,
309-
},
310293
"TTR": {
311294
"type": "totalTemperatureRatio",
312295
"source": "patchToFace",
@@ -354,7 +337,6 @@
354337

355338
funcs_ref = {
356339
"HFX": 2564.397361965973,
357-
"HFX_custom": 8967.626339020631,
358340
"TTR": 1.0002129350727795,
359341
"MFR": 128.2374484095998,
360342
"TPR": 0.9933893131111589,

0 commit comments

Comments
 (0)
Please sign in to comment.