Skip to content

Commit 38e3842

Browse files
committed
updated optimization tutorials
1 parent 781ceb0 commit 38e3842

9 files changed

+70
-81
lines changed

.DS_Store

0 Bytes
Binary file not shown.

images/Opt_Electronic_Conditions.png

381 KB
Loading

images/opt_battery_draw.png

-40.2 KB
Binary file not shown.

images/opt_battery_energy.png

-44.8 KB
Binary file not shown.

images/opt_solar_flux.png

370 KB
Loading
Loading
Loading

tutorials/jet_optimization.html

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -82,40 +82,44 @@ <h4 id="optimizepy">Optimize.py:</h4>
8282
<p>In this particular setup, there are two design variables: wing area and cruise altitude. The objective is to minimize fuel burn, and there is only one constraint: fuel margin. The default inputs are defined in the following lines.</p>
8383

8484
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
85-
# [ tag , initial, lb,ub) , scaling , units ]
86-
problem.inputs = np.array([
87-
[ 'wing_area' , 100 , ( 90. , 130. ) , 100. , Units.meter**2],
88-
[ 'cruise_altitude' , 11 , ( 9 , 14. ) , 10. , Units.km],
89-
])
85+
# [ tag , initial, (lb , ub) , scaling , units ]
86+
problem.inputs = np.array([
87+
[ 'wing_area' , 80 , ( 50. , 130. ) , 100. , Units.meter**2],
88+
[ 'cruise_altitude' , 8 , ( 6. , 12. ) , 10. , Units.km],
89+
])
90+
9091

9192
</code></pre></div></div>
9293

9394
<p>Each input parameter takes in 5 values; a tag (an identification to communicate between the optimizer and SUAVE), an initial value, set of bounds, a scale factor (many optimizers tend to be more effective when the input values are of order 1), as well as the units used.</p>
9495

9596
<p>The objective and constraints are defined in the lines below.</p>
9697

97-
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code># [ tag, scaling, units ]
98-
problem.objective = np.array([
99-
[ 'fuel_burn', 10000, Units.kg ]
100-
])
101-
102-
# [ tag, sense, edge, scaling, units ]
103-
problem.constraints = np.array([
104-
[ 'design_range_fuel_margin' , '&gt;', 0., 1E-1, Units.less],
105-
])
98+
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
99+
# [ tag, scaling, units ]
100+
problem.objective = np.array([
101+
[ 'fuel_burn', 10000, Units.kg ]
102+
])
103+
104+
# [ tag, sense, edge, scaling, units ]
105+
problem.constraints = np.array([
106+
[ 'design_range_fuel_margin' , '&gt;', 0., 1E-1, Units.less],
107+
])
108+
106109
</code></pre></div></div>
107110

108111
<p>Note that in this case, only a single constraint is used. Multiple constraints may be used using a list format, similar to the input variables.</p>
109112

110113
<p>This file also defines the “aliasing,” i.e. how the design variables, constraints, and objective map to the variables used in Procedure.py (which is where the problem is evaluated). The aliases for this problem are defined in the lines below. Note that the first entry refers to the tag defined in either problem.inputs, problem.objective, or problem.constraints.</p>
111114

112-
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>problem.aliases = [
113-
[ 'wing_area' , ['vehicle_configurations.*.wings.main_wing.areas.reference',
114-
'vehicle_configurations.*.reference_area' ]],
115-
[ 'cruise_altitude' , 'missions.base.segments.climb_5.altitude_end' ],
116-
[ 'fuel_burn' , 'summary.base_mission_fuelburn' ],
117-
[ 'design_range_fuel_margin' , 'summary.max_zero_fuel_margin' ],
118-
]
115+
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
116+
problem.aliases = [
117+
[ 'wing_area' , ['vehicle_configurations.*.wings.main_wing.areas.reference',
118+
'vehicle_configurations.*.reference_area' ]],
119+
[ 'cruise_altitude' , 'missions.base.segments.climb_5.altitude_end' ],
120+
[ 'fuel_burn' , 'summary.base_mission_fuelburn' ],
121+
[ 'design_range_fuel_margin' , 'summary.max_zero_fuel_margin' ],
122+
]
119123
</code></pre></div></div>
120124

121125
<p>Note that, sometimes, a single input can map to multiple outputs, such as the “wing_area” design variable; in this case, use a list for the outputs, as seen above. The use of a wild card “*”, can also allow values to map to multiple outputs. Values to be outputted cannot contain wild cards as that would be ambiguous to an optimizer.</p>
@@ -174,7 +178,8 @@ <h3 id="running-the-problem">Running the Problem:</h3>
174178
<h3 id="running-a-sweep-of-the-inputs">Running a Sweep of the Inputs</h3>
175179
<p>Now try running a 2D sweep of the problem to observe the shape of the design space: comment <code class="highlighter-rouge">output = problem.objective</code> then uncomment the following (the next line down in the code).</p>
176180

177-
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>variable_sweep(problem)
181+
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
182+
variable_sweep(problem)
178183
</code></pre></div></div>
179184

180185
<p>Then run the program again. This could take a few minutes. The results should look like the plot below.</p>
@@ -191,36 +196,17 @@ <h3 id="optimizing">Optimizing:</h3>
191196

192197
<p>Now try running an Optimization. Recomment <code class="highlighter-rouge">variable_sweep(problem)</code> then uncomment the lines below:</p>
193198

194-
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>output = scipy_setup.SciPy_Solve(problem,solver='SLSQP')
195-
print output
199+
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
200+
output = scipy_setup.SciPy_Solve(problem,solver='SLSQP')
201+
print output
196202
</code></pre></div></div>
197203

198204
<p>and run the file again.</p>
199205

200-
<p>From the default inputs, the terminal (or IDE output) should display an optimum of [ 1.08980937 1.02089232], which corresponds to a wing area of 109 m^2, and 10.2 km. It appears to have found the local minimum.</p>
206+
<p>From the default inputs, the terminal (or IDE output) should display an optimum of [0.57213139 0.75471681] which corresponds to a wing area of 58 m^2, and 7.5 km. It appears to have found a minima. Keep in mind that in designing a real regional jet the desingers would incorporate additional constraints and analyses. These additional constraints change the final design considerably</p>
201207

202-
<p>Now try starting the optimization from a different initial guess. You can either modify the input parameters in the initial formulation (the relevant lines are repeated below with the modification)</p>
203-
204-
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code># [ tag , initial, (lb,ub) , scaling , units ]
205-
problem.inputs = np.array([
206-
[ 'wing_area' , 128 , ( 90. , 130. ) , 100. , Units.meter**2],
207-
[ 'cruise_altitude' , 13.8 , ( 9 , 14. ) , 10. , Units.km],
208-
])
209208
</code></pre></div></div>
210209

211-
<p>or set up the optimization problem and change the inputs manually by uncommenting the following lines.</p>
212-
213-
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>inputs = [1.28, 1.38]
214-
scaling = problem.optimization_problem.inputs[:,3] # have to
215-
rescale inputs to start problem from here
216-
scaled_inputs = np.multiply(inputs,scaling)
217-
problem.optimization_problem.inputs[:,1] = scaled_inputs
218-
output = scipy_setup.SciPy_Solve(problem,solver='SLSQP')
219-
print output
220-
</code></pre></div></div>
221-
222-
<p>This starts the optimization problem above the feasible region (wing area = 128 m^2, altitude = 13.8 km), and results in a fuel burn that is 30 kg lower than the result using the initial guess. This illustrates the important of choosing a starting point when running optimization problem. Additionally, this demonstrates SUAVE’s ability to handle infeasible cases, showing that it can converge to a feasible case even when starting from an infeasible set of initial inputs.</p>
223-
224210
<p>At this point, you can explore other starting points, or alter the vehicle or mission properties in Vehicles.py or Missions.py. Additionally, feel free to start using this as the basis for creating custom optimization scripts.</p>
225211

226212
<br>

tutorials/solar_optimization.html

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ <h3 id="optimizepy">Optimize.py:</h3>
8484
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
8585
# [ tag , initial, [lb,ub], scaling, units ]
8686
problem.inputs = np.array([
87-
[ 'wing_area' , 0.62, ( 0.1, 1.5 ), 0.5, Units.meter ],
88-
[ 'aspect_ratio' , 13.5, ( 5.0, 20.0 ), 10.0, Units.less ],
89-
[ 'dynamic_pressure', 115.0, ( 1.0, 2000.0 ), 125.0, Units.pascals ],
90-
[ 'solar_ratio' , 0.0, ( 0.0, 0.97), 1.0, Units.less ],
91-
[ 'kv' , 900.0, ( 10.0, 1500.0 ), 800.0, Units['rpm/volt']],
87+
[ 'wing_area' , 0.5, ( 0.1, 1.5 ), 0.5, Units.meter ],
88+
[ 'aspect_ratio' , 10.0, ( 5.0, 20.0 ), 10.0, Units.less ],
89+
[ 'dynamic_pressure', 125.0, ( 1.0, 2000.0 ), 125.0, Units.pascals ],
90+
[ 'solar_ratio' , 0.0, ( 0.0, 0.97), 1.0, Units.less ],
91+
[ 'kv' , 800.0, ( 10.0, 10000.0 ), 800.0, Units['rpm/volt']],
9292
])
9393
</code></pre></div></div>
9494

@@ -121,15 +121,14 @@ <h3 id="vehiclespy">Vehicles.py:</h3>
121121
<p>Next, you will setup the vehicle. This is very similar to the prior Solar UAV tutorial, so we will gloss over this. The one noticeable difference is that a lower fidelity energy network is used. This means that most components operate with prescribed efficiencies. For example:</p>
122122

123123
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
124-
# Component 5 the Motor
124+
# Component 5 the Motor
125125
motor = SUAVE.Components.Energy.Converters.Motor_Lo_Fid()
126-
kv = 800. * Units['rpm/volt'] # RPM/volt is standard
127-
motor = size_from_kv(motor, kv)
126+
motor.speed_constant = 900. * Units['rpm/volt'] # RPM/volt is standard
127+
motor = size_from_kv(motor)
128128
motor.gear_ratio = 1. # Gear ratio, no gearbox
129129
motor.gearbox_efficiency = 1. # Gear box efficiency, no gearbox
130-
motor.motor_efficiency = 0.825;
131-
net.motor = motor
132-
])
130+
motor.motor_efficiency = 0.8;
131+
net.motor = motor
133132
</code></pre></div></div>
134133

135134
<h3 id="missionspy">Missions.py:</h3>
@@ -276,38 +275,42 @@ <h3 id="results">Results</h3>
276275
<p>Let’s look at the results:</p>
277276

278277
<div class="highlight_code"><div class="highlight_code"><pre class="highlight_code"><code>
279-
Optimization terminated successfully. (Exit mode 0)
280-
Current function value: [0.0]
281-
Iterations: 4
282-
Function evaluations: 29
283-
Gradient evaluations: 4
284-
[ 1.12963146 1.43880081 1.39329626 0.65589785 0.97171879]
285-
Design Variable Table:
286-
287-
[['wing_area' 0.5648157324099996 (0.1, 1.5) 0.5 1.0]
288-
['aspect_ratio' 14.388008119672202 (5.0, 20.0) 10.0 1.0]
289-
['dynamic_pressure' 174.16203234031317 (1.0, 2000.0) 125.0 1.0]
290-
['solar_ratio' 0.6558978486767236 (0.0, 0.97) 1.0 1.0]
291-
['kv' 777.3750338508712 (10.0, 1500.0) 800.0 0.10471975511965977]]
292-
293-
Constraint Table:
294-
295-
[['energy_constraint' 0.0 '=' 0.0 1.0 &lt;Quantity(1.0, 'less')&gt;]
296-
['battery_mass' 4.939962596982861 '&gt;' 0.0 1.0 &lt;Quantity(1.0, 'kilogram')&gt;]
297-
['CL' 0.5309682332699428 '&gt;' 0.0 1.0 &lt;Quantity(1.0, 'less')&gt;]
298-
['Throttle_min' 0.7319219623084848 '&gt;' 0.0 1.0 &lt;Quantity(1.0, 'less')&gt;]
299-
['Throttle_max' 0.1680780376915152 '&gt;' 0.0 1.0 &lt;Quantity(1.0, 'less')&gt;]]
278+
279+
Optimization terminated successfully. (Exit mode 0)
280+
Current function value: 0.0
281+
Iterations: 6
282+
Function evaluations: 43
283+
Gradient evaluations: 6
284+
Design Variable Table:
285+
286+
[['wing_area' 0.47033164669264826 (0.1, 1.5) 0.5 1.0]
287+
['aspect_ratio' 9.803406982966878 (5.0, 20.0) 10.0 1.0]
288+
['dynamic_pressure' 120.77967631598601 (1.0, 2000.0) 125.0 1.0]
289+
['solar_ratio' 0.09461785224148354 (0.0, 0.97) 1.0 1.0]
290+
['kv' 833.2503881434465 (10.0, 10000.0) 800.0 0.10471975511965977]]
291+
292+
Constraint Table:
293+
294+
[['energy_constraint' 4.835975275289128e-08 '=' 0.0 1.0
295+
&lt;Quantity(1.0, 'less')&gt;]
296+
['battery_mass' 2.046103692285638 '>' 0.0 1.0
297+
&lt;Quantity(1.0, 'kilogram')&gt;]
298+
['CL' 0.5131461964430024 '&gt;' 0.0 1.0 &lt;Quantity(1.0, 'less')&gt;
299+
['Throttle_min' 0.321677340768132 '>' 0.0 1.0 &lt;Quantity(1.0, 'less')&gt;]
300+
['Throttle_max' 0.578322659231868 '>' 0.0 1.0 &lt;Quantity(1.0, 'less')&gt;]]
301+
300302
</code></pre></div></div>
301303

302304
<p>Okay looks like SciPy found a feasible solution without too much time. Now let’s review the plots.</p>
303305

304-
<p><img src="/images/opt_battery_energy.png" alt="battery_energy" /></p>
306+
<p><img src="/images/Opt_Electronic_Conditions.png" alt="Electronics" /></p>
307+
308+
<p>So we can tell now that the battery energy doesn’t go all the way to zero. One thing to note, because we have a solar UAV the voltage is regulated differently and the C-rate doesn't apply in the same way.
305309

306-
<p>So we can tell now that the battery energy doesn’t go all the way to zero. Let’s look at how the solar flux varies throughout the day and how that affects the draw from the battery.</p>
310+
Let’s look at how the solar flux varies throughout the day and how that affects the draw from the battery.</p>
307311

308-
<p><img src="/images/opt_solar_flux.png" alt="solar flux" /></p>
312+
<p><img src="/images/Opt_solar_flux.png" alt="Solar Flux" /></p>
309313

310-
<p><img src="/images/opt_battery_draw.png" alt="battery draw" /></p>
311314

312315
<p>So maybe those solar panels actually are worth it. They seem to decrease the load on the battery considerably during the daytime.</p>
313316

0 commit comments

Comments
 (0)