Skip to content

Commit

Permalink
Merge pull request #437 from fast-aircraft-design/issue-436_configura…
Browse files Browse the repository at this point in the history
…tion_file_connections

Issue 436 - configuration file connections with indepvarcomp
  • Loading branch information
christophe-david committed May 18, 2022
2 parents 9af6c89 + e9441a0 commit a58e670
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@


title = "Sellar"

module_folders = [
"conf_sellar_example",
"d:/path/does/not/exist" # will only trigger a warning
]

input_file = "../results/inputs.xml"
output_file = "../results/outputs.xml"

driver = "om.ScipyOptimizeDriver(optimizer='SLSQP')"
[model]
[model.indep]
id = "configuration_test.sellar.indeps"
[[model.connections]]
source = "system:x"
target = "x"
[[model.connections]]
source = "y1"
target = "yy1"
[[model.connections]]
source = "y2"
target = "yy2"
[model.cycle]
nonlinear_solver = "om.NonlinearBlockGS(iprint=1)"
linear_solver = "om.ScipyKrylov()"
[model.cycle.disc1]
id = "configuration_test.sellar.disc1"
[model.cycle.disc2]
id = "configuration_test.sellar.disc2"
[model.functions]
id = "configuration_test.sellar.functions"

[submodels]
"service.function.f" = "function.f.default"
"service.function.g1" = "function.g1.default"
"service.function.g2" = "function.g2.default"

[optimization]
[[optimization.design_variables]]
name = "x"
lower = 0
upper = 10
[[optimization.design_variables]]
name = "z"
lower = 0
upper = 10

[[optimization.constraints]]
name = "g1"
lower = -100
upper = 0
[[optimization.constraints]]
name = "g2"
upper = 0

[[optimization.objective]]
name = "f"

30 changes: 30 additions & 0 deletions src/fastoad/io/configuration/tests/test_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,36 @@ def test_problem_definition_with_xml_ref(cleanup):
alt_problem["g1"] # submodel for g1 computation has been deactivated.


def test_problem_definition_with_xml_ref_with_indep(cleanup):
"""Tests what happens when writing inputs of a problem with indeps using data from existing XML file"""
for extension in ["toml", "yml"]:
clear_openmdao_registry()
conf = FASTOADProblemConfigurator(
pth.join(DATA_FOLDER_PATH, "valid_sellar_with_indep.%s" % extension)
)

result_folder_path = pth.join(
RESULTS_FOLDER_PATH, "problem_definition_with_xml_ref_with_indep"
)
conf.input_file_path = pth.join(result_folder_path, "inputs.xml")
conf.output_file_path = pth.join(result_folder_path, "outputs.xml")
ref_input_data_path = pth.join(DATA_FOLDER_PATH, "ref_inputs.xml")
conf.write_needed_inputs(ref_input_data_path)
input_data = DataFile(conf.input_file_path)
assert len(input_data) == 2
assert "system:x" in input_data.names()
assert "z" in input_data.names()

problem = conf.get_problem(read_inputs=True, auto_scaling=True)
# runs evaluation without optimization loop to check that inputs are taken into account
problem.setup()
# system:x is not in ref_inputs.xml
problem["system:x"] = 1.0
problem.run_model()
assert problem["f"] == pytest.approx(28.58830817, abs=1e-6)
problem.write_outputs()


# FIXME: this test should be reworked and moved to test_problem
def test_problem_definition_with_custom_xml(cleanup):
"""Tests what happens when writing inputs using existing XML with some unwanted var"""
Expand Down
15 changes: 10 additions & 5 deletions src/fastoad/openmdao/tests/test_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,13 +715,14 @@ def test_variables_from_unconnected_inputs_with_sellar_problem(cleanup):
def test_get_variables_from_problem_sellar_with_promotion_and_connect():
group = om.Group()
indeps = group.add_subsystem("indeps", om.IndepVarComp(), promotes=["*"])
indeps.add_output("x", 1.0)
indeps.add_output("indep:x", 1.0)
indeps.add_output("z", [5.0, 2.0])
group.add_subsystem("disc1", Disc1(), promotes=["x", "z"])
group.add_subsystem("disc2", Disc2(), promotes=["z"])
group.add_subsystem("functions", Functions(), promotes=["*"])

# Connections
group.connect("indep:x", "x")
group.connect("disc1.y1", "disc2.y1")
group.connect("disc2.y2", "disc1.y2")
group.connect("disc1.y1", "y1")
Expand All @@ -735,15 +736,17 @@ def test_get_variables_from_problem_sellar_with_promotion_and_connect():
vars = VariableList.from_problem(problem, use_initial_values=False, get_promoted_names=True)
assert vars_before_setup == vars

# x should be an output
assert not vars["x"].is_input
# y1 and y2 should be outputs
assert not vars["y1"].is_input
assert not vars["y2"].is_input
# f, g1 and g2 should be outputs
assert not vars["f"].is_input
assert not vars["g1"].is_input
assert not vars["g2"].is_input
# x and z as indeps should be inputs
assert vars["x"].is_input
# indep:x and z as indeps should be inputs
assert vars["indep:x"].is_input
assert vars["z"].is_input

# Test for io_status
Expand All @@ -758,6 +761,7 @@ def test_get_variables_from_problem_sellar_with_promotion_and_connect():
assert "g1" in vars.names()
assert "g2" in vars.names()
assert "x" in vars.names()
assert "indep:x" in vars.names()
assert "z" in vars.names()

# Check that only inputs are returned
Expand All @@ -770,7 +774,7 @@ def test_get_variables_from_problem_sellar_with_promotion_and_connect():
assert "f" not in vars.names()
assert "g1" not in vars.names()
assert "g2" not in vars.names()
assert "x" in vars.names()
assert "indep:x" in vars.names()
assert "z" in vars.names()

# Check that only outputs are returned
Expand All @@ -783,5 +787,6 @@ def test_get_variables_from_problem_sellar_with_promotion_and_connect():
assert "f" in vars.names()
assert "g1" in vars.names()
assert "g2" in vars.names()
assert "x" not in vars.names()
assert "x" in vars.names()
assert "indep:x" not in vars.names()
assert "z" not in vars.names()
14 changes: 8 additions & 6 deletions src/fastoad/openmdao/variables/variable_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def from_problem(
:param get_promoted_names: if True, promoted names will be returned instead of absolute ones
(if no promotion, absolute name will be returned)
:param promoted_only: if True, only promoted variable names will be returned
:param io_status: to choose with type of variable we return ("all", "inputs, "inputs")
:param io_status: to choose with type of variable we return ("all", "inputs, "outputs")
:return: VariableList instance
"""

Expand Down Expand Up @@ -302,7 +302,6 @@ def from_problem(
indep_outputs = problem.model.get_io_metadata(
"output", metadata_keys=metadata_keys, tags="indep_var"
)

# Move outputs from IndepVarComps into inputs
for abs_name, metadata in indep_outputs.items():
del outputs[abs_name]
Expand All @@ -325,10 +324,7 @@ def from_problem(
# Check connections
for name, metadata in inputs.copy().items():
source_name = problem.model.get_source(name)
if (
not (source_name in indep_outputs or source_name.startswith("_auto_ivc."))
and source_name != name
):
if not (source_name.startswith("_auto_ivc.")) and source_name != name:
# This variable is connected to another variable of the problem: it is
# not an actual problem input. Let's move it to outputs.
del inputs[name]
Expand All @@ -343,13 +339,19 @@ def from_problem(
# Manage variable promotion
if not get_promoted_names:
final_inputs = inputs

final_outputs = outputs
else:
final_inputs = {
metadata["prom_name"]: dict(metadata, is_input=True) for metadata in inputs.values()
}
final_outputs = cls._get_promoted_outputs(outputs)

# Remove possible duplicates due to Indeps
for input_name in final_inputs:
if input_name in final_outputs:
del final_outputs[input_name]

# When variables are promoted, we may have retained a definition of the variable
# that does not have any description, whereas a description is available in
# another related definition (issue #319).
Expand Down

0 comments on commit a58e670

Please sign in to comment.