Skip to content

Commit 28df52f

Browse files
Merge branch 'ssw' into ssw-14
2 parents 29a9f4c + 8849767 commit 28df52f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+31347
-2
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@ work
3030
*.pbs
3131
*.o*
3232
*.in
33+
examples/fun3d_examples/ssw_meshdef_optimization/geometry/port7681.jrnl
34+
examples/fun3d_examples/ssw_meshdef_optimization/geometry/autosave.csm
35+
**/Scratch
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.jrnl
2+
*.hst
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
"""
2+
1_panel_thickness.py
3+
4+
Run a coupled optimization of the panel thicknesses of the wing structure.
5+
No shape variables are included in this optimization.
6+
"""
7+
8+
from pyoptsparse import SNOPT, Optimization
9+
from funtofem import *
10+
from mpi4py import MPI
11+
from tacs import caps2tacs
12+
import os
13+
14+
comm = MPI.COMM_WORLD
15+
16+
base_dir = os.path.dirname(os.path.abspath(__file__))
17+
csm_path = os.path.join(base_dir, "geometry", "ssw.csm")
18+
19+
# Optimization options
20+
hot_start = False
21+
store_history = True
22+
23+
nprocs_tacs = 8
24+
25+
global_debug_flag = False
26+
27+
# Derivative test stuff
28+
FILENAME = "complex-step.txt"
29+
FILEPATH = os.path.join(base_dir, FILENAME)
30+
31+
aitken_file = os.path.join(base_dir, "aitken-hist.txt")
32+
33+
# FUNTOFEM MODEL
34+
# <----------------------------------------------------
35+
# Freestream quantities -- see README
36+
T_inf = 268.338 # Freestream temperature
37+
q_inf = 1.21945e4 # Dynamic pressure
38+
39+
# Construct the FUNtoFEM model
40+
f2f_model = FUNtoFEMmodel("ssw-sizing1")
41+
tacs_model = caps2tacs.TacsModel.build(
42+
csm_file=csm_path,
43+
comm=comm,
44+
problem_name="capsStruct1",
45+
active_procs=[0],
46+
verbosity=1,
47+
)
48+
tacs_model.mesh_aim.set_mesh(
49+
edge_pt_min=2,
50+
edge_pt_max=20,
51+
global_mesh_size=0.3,
52+
max_surf_offset=0.2,
53+
max_dihedral_angle=15,
54+
).register_to(tacs_model)
55+
f2f_model.structural = tacs_model
56+
57+
tacs_aim = tacs_model.tacs_aim
58+
tacs_aim.set_config_parameter("view:flow", 0)
59+
tacs_aim.set_config_parameter("view:struct", 1)
60+
61+
for proc in tacs_aim.active_procs:
62+
if comm.rank == proc:
63+
aim = tacs_model.mesh_aim.aim
64+
aim.input.Mesh_Sizing = {
65+
"chord": {"numEdgePoints": 20},
66+
"span": {"numEdgePoints": 8},
67+
"vert": {"numEdgePoints": 4},
68+
}
69+
70+
# add tacs constraints in
71+
caps2tacs.PinConstraint("root").register_to(tacs_model)
72+
73+
# ---------------------------------------------------->
74+
75+
# BODIES AND STRUCT DVs
76+
# <----------------------------------------------------
77+
78+
# wing = Body.aeroelastic("wing", boundary=3).relaxation(
79+
# AitkenRelaxation(
80+
# theta_init=0.6, theta_max=0.95, history_file=aitken_file, debug=True
81+
# )
82+
# )
83+
wing = Body.aeroelastic("wing", boundary=3)
84+
85+
# setup the material and shell properties
86+
aluminum = caps2tacs.Isotropic.aluminum().register_to(tacs_model)
87+
88+
nribs = int(tacs_model.get_config_parameter("nribs"))
89+
nspars = int(tacs_model.get_config_parameter("nspars"))
90+
nOML = nribs - 1
91+
92+
for irib in range(1, nribs + 1):
93+
name = f"rib{irib}"
94+
prop = caps2tacs.ShellProperty(
95+
caps_group=name, material=aluminum, membrane_thickness=0.04
96+
).register_to(tacs_model)
97+
Variable.structural(name, value=0.01).set_bounds(
98+
lower=0.001, upper=0.15, scale=100.0
99+
).register_to(wing)
100+
101+
for ispar in range(1, nspars + 1):
102+
name = f"spar{ispar}"
103+
prop = caps2tacs.ShellProperty(
104+
caps_group=name, material=aluminum, membrane_thickness=0.04
105+
).register_to(tacs_model)
106+
Variable.structural(name, value=0.01).set_bounds(
107+
lower=0.001, upper=0.15, scale=100.0
108+
).register_to(wing)
109+
110+
for iOML in range(1, nOML + 1):
111+
name = f"OML{iOML}"
112+
prop = caps2tacs.ShellProperty(
113+
caps_group=name, material=aluminum, membrane_thickness=0.04
114+
).register_to(tacs_model)
115+
Variable.structural(name, value=0.01).set_bounds(
116+
lower=0.001, upper=0.15, scale=100.0
117+
).register_to(wing)
118+
119+
for prefix in ["LE", "TE"]:
120+
name = f"{prefix}spar"
121+
prop = caps2tacs.ShellProperty(
122+
caps_group=name, material=aluminum, membrane_thickness=0.04
123+
).register_to(tacs_model)
124+
Variable.structural(name, value=0.01).set_bounds(
125+
lower=0.001, upper=0.15, scale=100.0
126+
).register_to(wing)
127+
128+
# register the wing body to the model
129+
wing.register_to(f2f_model)
130+
131+
# ---------------------------------------------------->
132+
133+
# INITIAL STRUCTURE MESH, SINCE NO STRUCT SHAPE VARS
134+
# <----------------------------------------------------
135+
136+
tacs_aim.setup_aim()
137+
tacs_aim.pre_analysis()
138+
139+
# ---------------------------------------------------->
140+
141+
# SCENARIOS
142+
# <----------------------------------------------------
143+
144+
# make a funtofem scenario
145+
cruise = Scenario.steady("pw-cruise", steps=5000, uncoupled_steps=0)
146+
mass = Function.mass().optimize(
147+
scale=1.0e-4, objective=True, plot=True, plot_name="mass"
148+
)
149+
ksfailure = Function.ksfailure(ks_weight=150.0, safety_factor=1.5).optimize(
150+
scale=1.0, upper=1.0, objective=False, plot=True, plot_name="ks-cruise"
151+
)
152+
cruise.include(ksfailure).include(mass)
153+
cruise.set_temperature(T_ref=T_inf, T_inf=T_inf)
154+
cruise.set_flow_ref_vals(qinf=q_inf)
155+
cruise.register_to(f2f_model)
156+
157+
# ---------------------------------------------------->
158+
159+
# COMPOSITE FUNCTIONS
160+
# <----------------------------------------------------
161+
162+
# skin thickness adjacency constraints
163+
variables = f2f_model.get_variables()
164+
section_prefix = ["rib", "OML"]
165+
section_nums = [nribs, nOML]
166+
for isection, prefix in enumerate(section_prefix):
167+
section_num = section_nums[isection]
168+
for iconstr in range(1, section_num):
169+
left_var = f2f_model.get_variables(names=f"{prefix}{iconstr}")
170+
right_var = f2f_model.get_variables(names=f"{prefix}{iconstr+1}")
171+
adj_constr = (left_var - right_var) / left_var
172+
adj_ratio = 0.15
173+
adj_constr.set_name(f"{prefix}{iconstr}-{iconstr+1}").optimize(
174+
lower=-adj_ratio, upper=adj_ratio, scale=1.0, objective=False
175+
).register_to(f2f_model)
176+
177+
# ---------------------------------------------------->
178+
179+
# DISCIPLINE INTERFACES AND DRIVERS
180+
# <----------------------------------------------------
181+
182+
solvers = SolverManager(comm)
183+
solvers.flow = Fun3dInterface(
184+
comm,
185+
f2f_model,
186+
fun3d_project_name="ssw-pw1.2",
187+
fun3d_dir="cfd",
188+
forward_tolerance=1e-7,
189+
adjoint_tolerance=1e-4,
190+
debug=global_debug_flag,
191+
)
192+
solvers.structural = TacsSteadyInterface.create_from_bdf(
193+
model=f2f_model,
194+
comm=comm,
195+
nprocs=nprocs_tacs,
196+
bdf_file=tacs_aim.root_dat_file,
197+
prefix=tacs_aim.root_analysis_dir,
198+
debug=global_debug_flag,
199+
)
200+
201+
transfer_settings = TransferSettings(npts=200)
202+
203+
# Build the FUNtoFEM driver
204+
f2f_driver = FUNtoFEMnlbgs(
205+
solvers=solvers,
206+
transfer_settings=transfer_settings,
207+
model=f2f_model,
208+
debug=global_debug_flag,
209+
)
210+
211+
# ---------------------------------------------------->
212+
213+
# PYOPTSPARSE OPTMIZATION
214+
# <----------------------------------------------------
215+
216+
# create an OptimizationManager object for the pyoptsparse optimization problem
217+
design_in_file = os.path.join(base_dir, "design", "sizing-oneway.txt")
218+
design_out_file = os.path.join(base_dir, "design", "design-1.txt")
219+
220+
design_folder = os.path.join(base_dir, "design")
221+
if comm.rank == 0:
222+
if not os.path.exists(design_folder):
223+
os.mkdir(design_folder)
224+
history_file = os.path.join(design_folder, "design-1.hst")
225+
store_history_file = history_file if store_history else None
226+
hot_start_file = history_file if hot_start else None
227+
228+
# Reload the previous design
229+
# f2f_model.read_design_variables_file(comm, design_in_file)
230+
231+
if comm.rank == 0:
232+
f2f_driver.print_summary()
233+
f2f_model.print_summary()
234+
235+
manager = OptimizationManager(
236+
f2f_driver,
237+
design_out_file=design_out_file,
238+
hot_start=hot_start,
239+
debug=global_debug_flag,
240+
hot_start_file=hot_start_file,
241+
)
242+
243+
# create the pyoptsparse optimization problem
244+
opt_problem = Optimization("sswOpt", manager.eval_functions)
245+
246+
# add funtofem model variables to pyoptsparse
247+
manager.register_to_problem(opt_problem)
248+
249+
# run an SNOPT optimization
250+
snoptimizer = SNOPT(options={"Verify level": 3})
251+
252+
sol = snoptimizer(
253+
opt_problem,
254+
sens=manager.eval_gradients,
255+
storeHistory=store_history_file,
256+
hotStart=hot_start_file,
257+
)
258+
259+
# print final solution
260+
sol_xdict = sol.xStar
261+
262+
if comm.rank == 0:
263+
print(f"Final solution = {sol_xdict}", flush=True)
264+
265+
# ---------------------------------------------------->

0 commit comments

Comments
 (0)