-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathairfoil_opt.py
More file actions
269 lines (240 loc) · 8.54 KB
/
airfoil_opt.py
File metadata and controls
269 lines (240 loc) · 8.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# ======================================================================
# Import modules
# ======================================================================
# rst Imports (beg)
import os
import numpy as np
from mpi4py import MPI
from baseclasses import AeroProblem
from adflow import ADFLOW
from pygeo import DVGeometry, DVConstraints
from pyoptsparse import Optimization, OPT
from idwarp import USMesh
from multipoint import multiPointSparse
# rst Imports (end)
# ======================================================================
# Specify parameters for optimization
# ======================================================================
# rst parameters (beg)
# cL constraint
mycl = 0.5
# angle of attack
alpha = 1.5
# mach number
mach = 0.75
# cruising altitude
alt = 10000
# rst parameters (end)
# ======================================================================
# Create multipoint communication object
# ======================================================================
# rst multipoint (beg)
MP = multiPointSparse(MPI.COMM_WORLD)
MP.addProcessorSet("cruise", nMembers=1, memberSizes=MPI.COMM_WORLD.size)
comm, setComm, setFlags, groupFlags, ptID = MP.createCommunicators()
setName = MP.getSetName()
outputDirectory = "output"
# if not os.path.exists(outputDirectory):
# os.mkdir(outputDirectory)
# else:
# raise OSError("The directory already exists! Please delete it or provide a new path")
ptDirs = MP.createDirectories(outputDirectory)
# rst multipoint (end)
# ======================================================================
# ADflow Set-up
# ======================================================================
# rst adflow (beg)
aeroOptions = {
# Common Parameters
"gridFile": "mesh/n0012.cgns",
"outputDirectory": ptDirs[setName][ptID],
# Physics Parameters
"equationType": "RANS",
"smoother": "DADI",
"MGCycle": "sg",
"nCycles": 20000,
"monitorvariables": ["resrho", "cl", "cd", "cmz", "yplus"],
"useNKSolver": True,
"useanksolver": True,
"nsubiterturb": 10,
"liftIndex": 2,
"infchangecorrection": True,
# Convergence Parameters
"L2Convergence": 1e-15,
"L2ConvergenceCoarse": 1e-4,
# Adjoint Parameters
"adjointSolver": "GMRES",
"adjointL2Convergence": 1e-12,
"ADPC": True,
"adjointMaxIter": 5000,
"adjointSubspaceSize": 400,
"ILUFill": 3,
"ASMOverlap": 3,
"outerPreconIts": 3,
"NKSubSpaceSize": 400,
"NKASMOverlap": 4,
"NKPCILUFill": 4,
"NKJacobianLag": 5,
"nkswitchtol": 1e-6,
"nkouterpreconits": 3,
"NKInnerPreConIts": 3,
"writeSurfaceSolution": False,
"writeVolumeSolution": False,
"frozenTurbulence": False,
"restartADjoint": False,
"setMonitor": True,
}
# Create solver
CFDSolver = ADFLOW(options=aeroOptions, comm=comm)
CFDSolver.addLiftDistribution(200, "z")
# rst adflow (end)
# ======================================================================
# Set up flow conditions with AeroProblem
# ======================================================================
# rst aeroproblem (beg)
ap = AeroProblem(name="fc", alpha=alpha, mach=mach, altitude=alt, areaRef=1.0, chordRef=1.0, evalFuncs=["cl", "cd"])
# Add angle of attack variable
ap.addDV("alpha", value=alpha, lower=0, upper=10.0, scale=1.0)
# rst aeroproblem (end)
# ======================================================================
# Geometric Design Variable Set-up
# ======================================================================
# rst dvgeo (beg)
# Create DVGeometry object
FFDFile = "ffd/ffd.xyz"
DVGeo = DVGeometry(FFDFile)
DVGeo.addGeoDVLocal("shape", lower=-0.05, upper=0.05, axis="y", scale=1.0)
#DVGeo.addGeoDVSpanwiseLocal("shape", 'k', lower=-0.05, upper=0.05, axis="y", scale=1.0)
span = 1.0
pos = np.array([0.5]) * span
CFDSolver.addSlices("z", pos, sliceType="absolute")
# Add DVGeo object to CFD solver
CFDSolver.setDVGeo(DVGeo)
# rst dvgeo (end)
# ======================================================================
# DVConstraint Setup
# ======================================================================
# rst dvcon (beg)
DVCon = DVConstraints()
DVCon.setDVGeo(DVGeo)
# Only ADflow has the getTriangulatedSurface Function
DVCon.setSurface(CFDSolver.getTriangulatedMeshSurface())
# Le/Te constraints
lIndex = DVGeo.getLocalIndex(0)
indSetA = []
indSetB = []
for k in range(0, 1):
indSetA.append(lIndex[0, 0, k]) # all DV for upper and lower should be same but different sign
indSetB.append(lIndex[0, 1, k])
for k in range(0, 1):
indSetA.append(lIndex[-1, 0, k])
indSetB.append(lIndex[-1, 1, k])
DVCon.addLeTeConstraints(0, indSetA=indSetA, indSetB=indSetB)
# # DV should be same along spanwise
# lIndex = DVGeo.getLocalIndex(0)
# indSetA = []
# indSetB = []
# for i in range(lIndex.shape[0]):
# indSetA.append(lIndex[i, 0, 0])
# indSetB.append(lIndex[i, 0, 1])
# for i in range(lIndex.shape[0]):
# indSetA.append(lIndex[i, 1, 0])
# indSetB.append(lIndex[i, 1, 1])
# DVCon.addLinearConstraintsShape(indSetA, indSetB, factorA=1.0, factorB=-1.0, lower=0, upper=0)
le = 0.0001
leList = [[le, 0, le], [le, 0, 1.0 - le]]
teList = [[1.0 - le, 0, le], [1.0 - le, 0, 1.0 - le]]
DVCon.addVolumeConstraint(leList, teList, 2, 100, lower=0.064837137176294343, upper=0.07, scaled=False)
DVCon.addThicknessConstraints2D(leList, teList, 2, 100, lower=0.1, upper=3.0)
if comm.rank == 0:
fileName = os.path.join(outputDirectory, "constraints.dat")
DVCon.writeTecplot(fileName)
# rst dvcon (end)
# ======================================================================
# Mesh Warping Set-up
# ======================================================================
# rst warp (beg)
meshOptions = {"gridFile": "mesh/n0012.cgns"}
mesh = USMesh(options=meshOptions, comm=comm)
CFDSolver.setMesh(mesh)
# rst warp (end)
# ======================================================================
# Functions:
# ======================================================================
# rst funcs (beg)
def cruiseFuncs(x):
if MPI.COMM_WORLD.rank == 0:
print(x)
# Set design vars
DVGeo.setDesignVars(x)
ap.setDesignVars(x)
# Run CFD
CFDSolver(ap)
# Evaluate functions
funcs = {}
DVCon.evalFunctions(funcs)
CFDSolver.evalFunctions(ap, funcs)
CFDSolver.checkSolutionFailure(ap, funcs)
if MPI.COMM_WORLD.rank == 0:
print(funcs)
return funcs
def cruiseFuncsSens(x, funcs):
funcsSens = {}
DVCon.evalFunctionsSens(funcsSens)
CFDSolver.evalFunctionsSens(ap, funcsSens)
CFDSolver.checkAdjointFailure(ap, funcsSens)
if MPI.COMM_WORLD.rank == 0:
print(funcsSens)
return funcsSens
def objCon(funcs, printOK):
# Assemble the objective and any additional constraints:
funcs["obj"] = funcs[ap["cd"]]
funcs["cl_con_" + ap.name] = funcs[ap["cl"]] - mycl
if printOK:
print("funcs in obj:", funcs)
return funcs
# rst funcs (end)
# ======================================================================
# Optimization Problem Set-up
# ======================================================================
# rst optprob (beg)
# Create optimization problem
optProb = Optimization("opt", MP.obj, comm=MPI.COMM_WORLD)
# Add objective
optProb.addObj("obj", scale=1e4)
# Add variables from the AeroProblem
ap.addVariablesPyOpt(optProb)
# Add DVGeo variables
DVGeo.addVariablesPyOpt(optProb)
# Add constraints
DVCon.addConstraintsPyOpt(optProb)
optProb.addCon("cl_con_" + ap.name, lower=0.0, upper=0.0, scale=1.0)
# The MP object needs the 'obj' and 'sens' function for each proc set,
# the optimization problem and what the objcon function is:
MP.setProcSetObjFunc("cruise", cruiseFuncs)
MP.setProcSetSensFunc("cruise", cruiseFuncsSens)
MP.setObjCon(objCon)
MP.setOptProb(optProb)
optProb.printSparsity()
# rst optprob (end)
# rst optimizer
# Set up optimizer
optimizer = "SLSQP"
if optimizer == "SLSQP":
optOptions = {"IFILE": os.path.join(outputDirectory, "SLSQP.out")}
opt = OPT("slsqp", options=optOptions)
elif optimizer == "SNOPT":
optOptions = {
"Major feasibility tolerance": 1e-4,
"Major optimality tolerance": 1e-4,
"Difference interval": 1e-3,
"Hessian full memory": None,
"Function precision": 1e-8,
"Print file": os.path.join(outputDirectory, "SNOPT_print.out"),
"Summary file": os.path.join(outputDirectory, "SNOPT_summary.out"),
}
opt = OPT("snopt", options=optOptions)
# Run Optimization
sol = opt(optProb, MP.sens, storeHistory=os.path.join(outputDirectory, "opt.hst"))
if MPI.COMM_WORLD.rank == 0:
print(sol)