Skip to content

Commit

Permalink
Merge pull request #174 from fast-aircraft-design/tutorial_update
Browse files Browse the repository at this point in the history
Tutorial update
  • Loading branch information
ScottDelbecq committed May 20, 2020
2 parents fc5d416 + b40de30 commit 07ba2d2
Show file tree
Hide file tree
Showing 12 changed files with 1,527 additions and 1,060 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:
id: cache-venv
with:
path: .venv
key: ${{ runner.os }}-Py${{ matrix.python-version }}-poetry_venv-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-Py${{ matrix.python-version }}-venv-${{ hashFiles('**/poetry.lock') }}

- name: Activate environment and install dependencies
run: poetry install
Expand Down
15 changes: 11 additions & 4 deletions src/fastoad/cmd/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,19 +364,23 @@ def write_xdsm(


def _run_problem(
configuration_file_path: str, overwrite: bool = False, mode="run_model"
configuration_file_path: str,
overwrite: bool = False,
mode="run_model",
auto_scaling: bool = False,
) -> FASTOADProblem:
"""
Runs problem according to provided file
:param configuration_file_path: problem definition
:param overwrite: if True, output file will be overwritten
:param mode: 'run_model' or 'run_driver'
:param auto_scaling: if True, automatic scaling is performed for design variables and constraints
:return: the OpenMDAO problem after run
"""

problem = FASTOADProblem()
problem.configure(configuration_file_path)
problem.configure(configuration_file_path, auto_scaling=auto_scaling)

outputs_path = pth.normpath(problem.output_file_path)
if not overwrite and pth.exists(outputs_path):
Expand Down Expand Up @@ -416,15 +420,18 @@ def evaluate_problem(configuration_file_path: str, overwrite: bool = False) -> F
return _run_problem(configuration_file_path, overwrite, "run_model")


def optimize_problem(configuration_file_path: str, overwrite: bool = False) -> FASTOADProblem:
def optimize_problem(
configuration_file_path: str, overwrite: bool = False, auto_scaling: bool = False
) -> FASTOADProblem:
"""
Runs driver according to provided problem file
:param configuration_file_path: problem definition
:param overwrite: if True, output file will be overwritten
:param auto_scaling: if True, automatic scaling is performed for design variables and constraints
:return: the OpenMDAO problem after run
"""
return _run_problem(configuration_file_path, overwrite, "run_driver")
return _run_problem(configuration_file_path, overwrite, "run_driver", auto_scaling=auto_scaling)


def optimization_viewer(configuration_file_path: str):
Expand Down
25 changes: 10 additions & 15 deletions src/fastoad/cmd/resources/fastoad.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ input_file = "./problem_inputs.xml"
output_file = "./problem_outputs.xml"

# Definition of problem driver assuming the OpenMDAO convention "import openmdao.api as om"
driver = "om.ScipyOptimizeDriver()"
driver = "om.ScipyOptimizeDriver(tol=1e-6, optimizer='COBYLA')"

# Definition of OpenMDAO model
[model]
# Solvers are defined assuming the OpenMDAO convention "import openmdao.api as om"
nonlinear_solver = "om.NonlinearBlockGS(maxiter=100)"
nonlinear_solver = "om.NonlinearBlockGS(maxiter=200)"
linear_solver = "om.DirectSolver()"

# AlThough "model" is a mandatory name for the top level of the model, its sub-components can be freely named by user
Expand Down Expand Up @@ -41,19 +41,14 @@ driver = "om.ScipyOptimizeDriver()"

[optimization]
[[optimization.design_var]]
name = "data:geometry:wing:MAC:at25percent:x"
lower = 10.0
upper = 25.0
ref = 15.0

[[optimization.design_var]]
name = "data:geometry:wing:aspect_ratio"
lower = 6.0
upper = 12.0
name = "data:geometry:wing:MAC:at25percent:x"
lower = 16.0
upper = 18.0

[[optimization.constraint]]
name = "data:geometry:wing:span"
upper = 35.0
name = "data:handling_qualities:static_margin"
lower = 0.05
upper = 0.1

[[optimization.objective]]
name = "data:handling_qualities:static_margin:to_target"
[[optimization.objective]]
name = "data:mission:sizing:fuel"
21 changes: 18 additions & 3 deletions src/fastoad/io/configuration/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,28 @@ def __init__(self, *args, **kwargs):
self._conf_dict = {}
self.input_file_path = None
self.output_file_path = None
self._auto_scaling = False

def run_model(self, case_prefix=None, reset_iter_counts=True):
super().run_model()
status = super().run_model(case_prefix, reset_iter_counts)
ValidityDomainChecker.check_problem_variables(self)
return status

def run_driver(self, case_prefix=None, reset_iter_counts=True):
super().run_driver()
status = super().run_driver(case_prefix, reset_iter_counts)
ValidityDomainChecker.check_problem_variables(self)
return status

def configure(self, conf_file):
def configure(self, conf_file, auto_scaling: bool = False):
"""
Reads definition of the current problem in given file.
:param conf_file: Path to the file to open or a file descriptor
:param auto_scaling: if True, automatic scaling is performed for design variables and constraints
"""

self._conf_file = conf_file
self._auto_scaling = auto_scaling

conf_dirname = pth.dirname(pth.abspath(conf_file)) # for resolving relative paths
with open(conf_file, "r") as file:
Expand Down Expand Up @@ -267,6 +272,11 @@ def _add_constraints(self):
# Constraints
constraint_tables = optimization_definition.get(TABLES_CONSTRAINT, {})
for _, constraint_table in constraint_tables.items():
if self._auto_scaling:
if "lower" in constraint_table:
constraint_table["ref0"] = constraint_table["lower"]
if "upper" in constraint_table:
constraint_table["ref"] = constraint_table["upper"]
self.model.add_constraint(**constraint_table)

def _add_objectives(self):
Expand All @@ -281,6 +291,11 @@ def _add_design_vars(self):
optimization_definition = self.get_optimization_definition()
design_var_tables = optimization_definition.get(TABLES_DESIGN_VAR, {})
for _, design_var_table in design_var_tables.items():
if self._auto_scaling:
if "lower" in design_var_table:
design_var_table["ref0"] = design_var_table["lower"]
if "upper" in design_var_table:
design_var_table["ref"] = design_var_table["upper"]
self.model.add_design_var(**design_var_table)

def get_optimization_definition(self) -> Dict:
Expand Down
18 changes: 0 additions & 18 deletions src/fastoad/models/handling_qualities/compute_static_margin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ class ComputeStaticMargin(om.ExplicitComponent):
"""
Computation of static margin i.e. difference between CG ratio and neutral
point.
If option 'target' is provided, this module will provide the output
`data:handling_qualities:static_margin:to_target` that can be used as
objective function in an optimization problem.
"""

def initialize(self):
Expand All @@ -37,13 +33,6 @@ def setup(self):
self.add_input("data:aerodynamics:cruise:neutral_point:x", val=np.nan)

self.add_output("data:handling_qualities:static_margin")
if self.options["target"]:
self.add_output(
"data:handling_qualities:static_margin:to_target",
desc="objective function to minimize to 0. for getting "
"static margin close to fixed target (equal to the "
"square of 100 times the difference to target)",
)

self.declare_partials("*", "*", method="fd")

Expand All @@ -52,10 +41,3 @@ def compute(self, inputs, outputs, discrete_inputs=None, discrete_outputs=None):
ac_ratio = inputs["data:aerodynamics:cruise:neutral_point:x"]

outputs["data:handling_qualities:static_margin"] = ac_ratio - cg_ratio

if self.options["target"]:
static_margin = 100 * outputs["data:handling_qualities:static_margin"]
target = 100 * self.options["target"]
outputs["data:handling_qualities:static_margin:to_target"] = (
target - static_margin
) ** 2
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,3 @@ def test_compute_static_margin(input_xml):
problem = run_system(ComputeStaticMargin(), input_vars)
static_margin = problem["data:handling_qualities:static_margin"]
assert static_margin == pytest.approx(0.098550, abs=1e-6)

problem = run_system(ComputeStaticMargin(target=0.05), input_vars)
static_margin = problem["data:handling_qualities:static_margin:to_target"]
assert static_margin == pytest.approx(4.8550 ** 2, abs=1e-6)

problem = run_system(ComputeStaticMargin(target=0.15), input_vars)
static_margin = problem["data:handling_qualities:static_margin:to_target"]
assert static_margin == pytest.approx(5.1450 ** 2, abs=1e-6)
2 changes: 1 addition & 1 deletion src/fastoad/models/weight/cg/cg.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def setup(self):
# Solvers setup
self.nonlinear_solver = om.NonlinearBlockGS()
self.nonlinear_solver.options["iprint"] = 0
self.nonlinear_solver.options["maxiter"] = 100
self.nonlinear_solver.options["maxiter"] = 200

self.linear_solver = om.LinearBlockGS()
self.linear_solver.options["iprint"] = 0
Expand Down

0 comments on commit 07ba2d2

Please sign in to comment.