Skip to content

Commit 1931104

Browse files
authored
Added aeroOpt test (#755)
* Added unit test for primal. * Added the aeroOpt test. * Deleted the rhoSimple test. * Minor changes to the primal test.
1 parent cdc5d0c commit 1931104

7 files changed

+304
-221
lines changed
File renamed without changes.

tests/refs/DAFoam_Test_AeroOptRef.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Dictionary Key: CD
2+
@value 0.0167462707303083 1e-05 1e-10
3+
Dictionary Key: CL
4+
@value 0.2992242625146929 1e-05 1e-10

tests/refs/DAFoam_Test_DARhoSimpleFoamRef.txt

-14
This file was deleted.

tests/refs/DAFoam_Test_DASimpleFoamRef.txt

-39
This file was deleted.

tests/runRegTests_AeroOpt.py

+233
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
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, OptFuncs
14+
from mphys.scenario_aerodynamic import ScenarioAerodynamic
15+
from pygeo.mphys import OM_DVGEOCOMP
16+
from pygeo import geo_utils
17+
18+
gcomm = MPI.COMM_WORLD
19+
20+
os.chdir("./reg_test_files-main/NACA0012")
21+
if gcomm.rank == 0:
22+
os.system("rm -rf 0 system processor* *.bin")
23+
os.system("cp -r 0.incompressible 0")
24+
os.system("cp -r system.incompressible system")
25+
os.system("cp -r constant/turbulenceProperties.sa constant/turbulenceProperties")
26+
replace_text_in_file("system/fvSchemes", "meshWave;", "meshWaveFrozen;")
27+
28+
# aero setup
29+
U0 = 10.0
30+
p0 = 0.0
31+
A0 = 0.1
32+
twist0 = 3.0
33+
LRef = 1.0
34+
nuTilda0 = 4.5e-5
35+
36+
daOptions = {
37+
"designSurfaces": ["wing"],
38+
"solverName": "DASimpleFoam",
39+
"primalMinResTol": 1.0e-10,
40+
"primalMinResTolDiff": 1e4,
41+
"writeDeformedFFDs": True,
42+
"writeDeformedConstraints": True,
43+
"primalBC": {
44+
"U0": {"variable": "U", "patches": ["inout"], "value": [U0, 0.0, 0.0]},
45+
"p0": {"variable": "p", "patches": ["inout"], "value": [p0]},
46+
"nuTilda0": {"variable": "nuTilda", "patches": ["inout"], "value": [nuTilda0]},
47+
"useWallFunction": True,
48+
"transport:nu": 1.5e-5,
49+
},
50+
"function": {
51+
"CD": {
52+
"type": "force",
53+
"source": "patchToFace",
54+
"patches": ["wing"],
55+
"directionMode": "parallelToFlow",
56+
"patchVelocityInputName": "patchV",
57+
"scale": 1.0 / (0.5 * U0 * U0 * A0),
58+
},
59+
"CL": {
60+
"type": "force",
61+
"source": "patchToFace",
62+
"patches": ["wing"],
63+
"directionMode": "normalToFlow",
64+
"patchVelocityInputName": "patchV",
65+
"scale": 1.0 / (0.5 * U0 * U0 * A0),
66+
},
67+
"skewness": {
68+
"type": "meshQualityKS",
69+
"source": "allCells",
70+
"coeffKS": 10.0,
71+
"metric": "faceSkewness",
72+
"scale": 1.0,
73+
},
74+
"nonOrtho": {
75+
"type": "meshQualityKS",
76+
"source": "allCells",
77+
"coeffKS": 1.0,
78+
"metric": "nonOrthoAngle",
79+
"scale": 1.0,
80+
},
81+
},
82+
"adjEqnOption": {"gmresRelTol": 1.0e-10, "pcFillLevel": 1, "jacMatReOrdering": "rcm"},
83+
"normalizeStates": {"U": U0, "p": U0 * U0 / 2.0, "phi": 1.0, "nuTilda": 1e-3},
84+
"inputInfo": {
85+
"aero_vol_coords": {"type": "volCoord", "components": ["solver", "function"]},
86+
"patchV": {
87+
"type": "patchVelocity",
88+
"patches": ["inout"],
89+
"flowAxis": "x",
90+
"normalAxis": "y",
91+
"components": ["solver", "function"],
92+
},
93+
},
94+
}
95+
96+
meshOptions = {
97+
"gridFile": os.getcwd(),
98+
"fileType": "OpenFOAM",
99+
# point and normal for the symmetry plane
100+
"symmetryPlanes": [[[0.0, 0.0, 0.0], [0.0, 0.0, 1.0]], [[0.0, 0.0, 0.1], [0.0, 0.0, 1.0]]],
101+
}
102+
103+
104+
class Top(Multipoint):
105+
def setup(self):
106+
dafoam_builder = DAFoamBuilder(daOptions, meshOptions, scenario="aerodynamic")
107+
dafoam_builder.initialize(self.comm)
108+
109+
################################################################################
110+
# MPHY setup
111+
################################################################################
112+
113+
# ivc to keep the top level DVs
114+
self.add_subsystem("dvs", om.IndepVarComp(), promotes=["*"])
115+
116+
# create the mesh and cruise scenario because we only have one analysis point
117+
self.add_subsystem("mesh", dafoam_builder.get_mesh_coordinate_subsystem())
118+
119+
# add the geometry component, we dont need a builder because we do it here.
120+
self.add_subsystem("geometry", OM_DVGEOCOMP(file="FFD/wingFFD.xyz", type="ffd"))
121+
122+
self.mphys_add_scenario("cruise", ScenarioAerodynamic(aero_builder=dafoam_builder))
123+
124+
self.connect("mesh.x_aero0", "geometry.x_aero_in")
125+
self.connect("geometry.x_aero0", "cruise.x_aero")
126+
127+
self.add_subsystem("LoD", om.ExecComp("val=CL/CD"))
128+
129+
def configure(self):
130+
131+
# create geometric DV setup
132+
points = self.mesh.mphys_get_surface_mesh()
133+
134+
# add pointset
135+
self.geometry.nom_add_discipline_coords("aero", points)
136+
137+
# create constraint DV setup
138+
tri_points = self.mesh.mphys_get_triangulated_surface()
139+
self.geometry.nom_setConstraintSurface(tri_points)
140+
141+
# add the dv_geo object to the builder solver. This will be used to write deformed FFDs
142+
self.cruise.coupling.solver.add_dvgeo(self.geometry.DVGeo)
143+
144+
# add the dv_con object to the builder solver. This will be used to write deformed constraints
145+
self.cruise.coupling.solver.add_dvcon(self.geometry.DVCon)
146+
147+
# geometry setup
148+
149+
# Select all points
150+
pts = self.geometry.DVGeo.getLocalIndex(0)
151+
indexList = pts[:, :, :].flatten()
152+
PS = geo_utils.PointSelect("list", indexList)
153+
nShapes = self.geometry.nom_addLocalDV(dvName="shape", pointSelect=PS)
154+
155+
# setup the symmetry constraint to link the y displacement between k=0 and k=1
156+
nFFDs_x = pts.shape[0]
157+
nFFDs_y = pts.shape[1]
158+
indSetA = []
159+
indSetB = []
160+
for i in range(nFFDs_x):
161+
for j in range(nFFDs_y):
162+
indSetA.append(pts[i, j, 0])
163+
indSetB.append(pts[i, j, 1])
164+
self.geometry.nom_addLinearConstraintsShape("linearcon", indSetA, indSetB, factorA=1.0, factorB=-1.0)
165+
166+
# setup the volume and thickness constraints
167+
leList = [[1e-4, 0.0, 1e-4], [1e-4, 0.0, 0.1 - 1e-4]]
168+
teList = [[0.998 - 1e-4, 0.0, 1e-4], [0.998 - 1e-4, 0.0, 0.1 - 1e-4]]
169+
self.geometry.nom_addThicknessConstraints2D("thickcon", leList, teList, nSpan=2, nChord=10)
170+
self.geometry.nom_addVolumeConstraint("volcon", leList, teList, nSpan=2, nChord=10)
171+
# add the LE/TE constraints
172+
self.geometry.nom_add_LETEConstraint("lecon", volID=0, faceID="iLow", topID="k")
173+
self.geometry.nom_add_LETEConstraint("tecon", volID=0, faceID="iHigh", topID="k")
174+
175+
# add the design variables to the dvs component's output
176+
self.dvs.add_output("shape", val=np.zeros(nShapes))
177+
self.dvs.add_output("patchV", val=np.array([10.0, 3.0]))
178+
# manually connect the dvs output to the geometry and cruise
179+
self.connect("shape", "geometry.shape")
180+
self.connect("patchV", "cruise.patchV")
181+
182+
# define the design variables to the top level
183+
self.add_design_var("shape", lower=-0.1, upper=0.1, scaler=1.0)
184+
self.add_design_var("patchV", lower=-50.0, upper=50.0, scaler=1.0, indices=[1])
185+
186+
# add constraints and the objective
187+
self.connect("cruise.aero_post.CD", "LoD.CD")
188+
self.connect("cruise.aero_post.CL", "LoD.CL")
189+
self.add_objective("LoD.val", scaler=-1.0)
190+
self.add_constraint("cruise.aero_post.CL", equals=0.3)
191+
self.add_constraint("cruise.aero_post.skewness", upper=4.0)
192+
self.add_constraint("cruise.aero_post.nonOrtho", upper=70.0)
193+
self.add_constraint("geometry.thickcon", lower=0.5, upper=3.0, scaler=1.0)
194+
self.add_constraint("geometry.volcon", lower=1.0, scaler=1.0)
195+
self.add_constraint("geometry.tecon", equals=0.0, scaler=1.0, linear=True)
196+
self.add_constraint("geometry.lecon", equals=0.0, scaler=1.0, linear=True)
197+
self.add_constraint("geometry.linearcon", equals=0.0, scaler=1.0, linear=True)
198+
199+
200+
prob = om.Problem()
201+
prob.model = Top()
202+
203+
prob.driver = om.pyOptSparseDriver()
204+
prob.driver.options["optimizer"] = "IPOPT"
205+
prob.driver.opt_settings = {
206+
"tol": 1.0e-5,
207+
"constr_viol_tol": 1.0e-5,
208+
"max_iter": 2,
209+
"print_level": 5,
210+
"mu_strategy": "adaptive",
211+
"limited_memory_max_history": 10,
212+
"nlp_scaling_method": "none",
213+
"alpha_for_y": "full",
214+
"recalc_y": "yes",
215+
}
216+
prob.driver.options["debug_print"] = ["nl_cons", "objs", "desvars"]
217+
218+
prob.setup(mode="rev")
219+
om.n2(prob, show_browser=False, outfile="mphys_aero.html")
220+
221+
optFuncs = OptFuncs(daOptions, prob)
222+
223+
optFuncs.findFeasibleDesign(
224+
["cruise.aero_post.CL"], ["patchV"], designVarsComp=[1], targets=[0.3]
225+
)
226+
227+
prob.run_driver()
228+
229+
if gcomm.rank == 0:
230+
funcDict = {}
231+
funcDict["CD"] = prob.get_val("cruise.aero_post.CD")
232+
funcDict["CL"] = prob.get_val("cruise.aero_post.CL")
233+
reg_write_dict(funcDict, 1e-5, 1e-10)

0 commit comments

Comments
 (0)