Skip to content

Commit 3f6adab

Browse files
Chris PsenicaChris Psenica
Chris Psenica
authored and
Chris Psenica
committed
Adding in unit test for CHT daCustom based on the conjugate straight channel v4 case
1 parent 6a66484 commit 3f6adab

File tree

1 file changed

+239
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)