From c7b96dd3332a400969efcd56af847840032fa4ca Mon Sep 17 00:00:00 2001 From: lucaeros Date: Tue, 9 May 2023 14:31:40 -0400 Subject: [PATCH 01/12] chord scaling position --- openaerostruct/geometry/geometry_mesh.py | 7 ++++++- .../geometry/geometry_mesh_transformations.py | 19 ++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/openaerostruct/geometry/geometry_mesh.py b/openaerostruct/geometry/geometry_mesh.py index 9e9a01cc9..82948222b 100644 --- a/openaerostruct/geometry/geometry_mesh.py +++ b/openaerostruct/geometry/geometry_mesh.py @@ -79,10 +79,15 @@ def setup(self): val = np.ones(ny) if "chord_cp" in surface: promotes = ["chord"] + if "chord_scaling_pos" in surface: + gamma = surface["chord_scaling_pos"] + else : + gamma = 0.25 #if no scaling position is specified : chord scaling w.r.t quarter of chord else: promotes = [] + gamma = 0.25 - self.add_subsystem("scale_x", ScaleX(val=val, mesh_shape=mesh_shape), promotes_inputs=promotes) + self.add_subsystem("scale_x", ScaleX(val=val, mesh_shape=mesh_shape, gamma = gamma), promotes_inputs=promotes) # 3. Sweep diff --git a/openaerostruct/geometry/geometry_mesh_transformations.py b/openaerostruct/geometry/geometry_mesh_transformations.py index 89ac16cec..80918c6eb 100644 --- a/openaerostruct/geometry/geometry_mesh_transformations.py +++ b/openaerostruct/geometry/geometry_mesh_transformations.py @@ -131,11 +131,12 @@ def initialize(self): """ self.options.declare("val", desc="Initial value for chord lengths") self.options.declare("mesh_shape", desc="Tuple containing mesh shape (nx, ny).") + self.options.declare("gamma", default = 0.25,desc="float in [0.,1.] which indicates the chord fraction where to do the chord scaling. 1. is trailing edge, 0. is leading edge") def setup(self): mesh_shape = self.options["mesh_shape"] val = self.options["val"] - + self.gamma = self.options["gamma"] self.add_input("chord", units="m", val=val) self.add_input("in_mesh", shape=mesh_shape, units="m") @@ -166,9 +167,9 @@ def compute(self, inputs, outputs): te = mesh[-1] le = mesh[0] - quarter_chord = 0.25 * te + 0.75 * le + gamma_chord = self.gamma * te + (1-self.gamma) * le - outputs["mesh"] = np.einsum("ijk,j->ijk", mesh - quarter_chord, chord_dist) + quarter_chord + outputs["mesh"] = np.einsum("ijk,j->ijk", mesh - gamma_chord, chord_dist) + gamma_chord def compute_partials(self, inputs, partials): mesh = inputs["in_mesh"] @@ -176,9 +177,9 @@ def compute_partials(self, inputs, partials): te = mesh[-1] le = mesh[0] - quarter_chord = 0.25 * te + 0.75 * le + gamma_chord = self.gamma * te + (1-self.gamma) * le - partials["mesh", "chord"] = (mesh - quarter_chord).flatten() + partials["mesh", "chord"] = (mesh - gamma_chord).flatten() nx, ny, _ = mesh.shape nn = nx * ny * 3 @@ -187,12 +188,12 @@ def compute_partials(self, inputs, partials): d_qc = (np.einsum("ij,i->ij", np.ones((ny, 3)), 1.0 - chord_dist)).flatten() nnq = (nx - 1) * ny * 3 - partials["mesh", "in_mesh"][nn : nn + nnq] = np.tile(0.25 * d_qc, nx - 1) - partials["mesh", "in_mesh"][nn + nnq :] = np.tile(0.75 * d_qc, nx - 1) + partials["mesh", "in_mesh"][nn : nn + nnq] = np.tile(self.gamma * d_qc, nx - 1) + partials["mesh", "in_mesh"][nn + nnq :] = np.tile((1-self.gamma) * d_qc, nx - 1) nnq = ny * 3 - partials["mesh", "in_mesh"][nn - nnq : nn] += 0.25 * d_qc - partials["mesh", "in_mesh"][:nnq] += 0.75 * d_qc + partials["mesh", "in_mesh"][nn - nnq : nn] += self.gamma * d_qc + partials["mesh", "in_mesh"][:nnq] += (1-self.gamma) * d_qc class Sweep(om.ExplicitComponent): From ed77a1ca6e0d3be4289d3709805546b992e23073 Mon Sep 17 00:00:00 2001 From: lucaeros Date: Tue, 9 May 2023 15:12:19 -0400 Subject: [PATCH 02/12] flake8 --- .flake8 | 1 + 1 file changed, 1 insertion(+) diff --git a/.flake8 b/.flake8 index 7dfa6ed49..627eef614 100644 --- a/.flake8 +++ b/.flake8 @@ -6,3 +6,4 @@ extend-exclude = openaerostruct/docs/_utils/docutil.py, openaerostruct/docs/_utils/patch.py, openaerostruct/utils/plot_*.py, + From 569bfbf07487fccda75a67f4529b5eac3ddc9e29 Mon Sep 17 00:00:00 2001 From: lucaeros Date: Tue, 9 May 2023 15:34:52 -0400 Subject: [PATCH 03/12] flake8 balc --- .flake8 | 58 +++++++++++++++++++ .gitignore | 1 + openaerostruct/geometry/geometry_mesh.py | 6 +- .../geometry/geometry_mesh_transformations.py | 14 +++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/.flake8 b/.flake8 index 627eef614..295804467 100644 --- a/.flake8 +++ b/.flake8 @@ -7,3 +7,61 @@ extend-exclude = openaerostruct/docs/_utils/patch.py, openaerostruct/utils/plot_*.py, +max-line-length = 120 + +extend-ignore = + # black + E203, + # too many leading '#' for block comment + E266, + # expected 2 blank lines, found 1 + E302, + # do not use mutable data structures for argument defaults (too many false positives) + B006, + # ===== TODO: to be fixed: + # invalid escape sequence, necessary for sphinx directives in docstrings but should switch to raw string + W605, + # line length, exceeded by some docstrings + E501, + # Function definition does not bind loop variable, happens everywhere in our code + B023, + # pydocstyle + D + +# Only add patterns here that are not included by the defaults of flake8 or other plugins +# extend-select = + +# flake8-docstrings +docstring-convention = numpy + +# flake8-rst-docstrings +rst-roles = + class, + func, + ref, + meth, + +rst-directives = + # Custom directives defined in the sphinx_mdolab_theme + embed-compare, + embed-bibtex, + embed-code, + embed-shell-cmd, + embed-n2, + +# mccabe complexity +# max-complexity = 10 + +# ignored files/directories +# we use exclude here and extend-exclude in repo-specific config files +# so that we can pass both to flake8 directly without needing to merge them first +exclude = + # No need to traverse the git directory + .git, + # There's no value in checking cache directories + __pycache__, + # The conf file is mostly autogenerated, ignore it + doc/conf.py, + # No need for init and setup files + __init__.py, + setup.py, diff --git a/.gitignore b/.gitignore index 8582ff81f..933c0562b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ src/adjoint/tempForward/ openaerostruct.egg-info/ .vscode *.plt +.pre-commit-config.yaml diff --git a/openaerostruct/geometry/geometry_mesh.py b/openaerostruct/geometry/geometry_mesh.py index 82948222b..31a21d161 100644 --- a/openaerostruct/geometry/geometry_mesh.py +++ b/openaerostruct/geometry/geometry_mesh.py @@ -81,13 +81,13 @@ def setup(self): promotes = ["chord"] if "chord_scaling_pos" in surface: gamma = surface["chord_scaling_pos"] - else : - gamma = 0.25 #if no scaling position is specified : chord scaling w.r.t quarter of chord + else: + gamma = 0.25 # if no scaling position is specified : chord scaling w.r.t quarter of chord else: promotes = [] gamma = 0.25 - self.add_subsystem("scale_x", ScaleX(val=val, mesh_shape=mesh_shape, gamma = gamma), promotes_inputs=promotes) + self.add_subsystem("scale_x", ScaleX(val=val, mesh_shape=mesh_shape, gamma=gamma), promotes_inputs=promotes) # 3. Sweep diff --git a/openaerostruct/geometry/geometry_mesh_transformations.py b/openaerostruct/geometry/geometry_mesh_transformations.py index 80918c6eb..e6ad44799 100644 --- a/openaerostruct/geometry/geometry_mesh_transformations.py +++ b/openaerostruct/geometry/geometry_mesh_transformations.py @@ -131,7 +131,11 @@ def initialize(self): """ self.options.declare("val", desc="Initial value for chord lengths") self.options.declare("mesh_shape", desc="Tuple containing mesh shape (nx, ny).") - self.options.declare("gamma", default = 0.25,desc="float in [0.,1.] which indicates the chord fraction where to do the chord scaling. 1. is trailing edge, 0. is leading edge") + self.options.declare( + "gamma", + default=0.25, + desc="float in [0.,1.] which indicates the chord fraction where to do the chord scaling. 1. is trailing edge, 0. is leading edge", + ) def setup(self): mesh_shape = self.options["mesh_shape"] @@ -167,7 +171,7 @@ def compute(self, inputs, outputs): te = mesh[-1] le = mesh[0] - gamma_chord = self.gamma * te + (1-self.gamma) * le + gamma_chord = self.gamma * te + (1 - self.gamma) * le outputs["mesh"] = np.einsum("ijk,j->ijk", mesh - gamma_chord, chord_dist) + gamma_chord @@ -177,7 +181,7 @@ def compute_partials(self, inputs, partials): te = mesh[-1] le = mesh[0] - gamma_chord = self.gamma * te + (1-self.gamma) * le + gamma_chord = self.gamma * te + (1 - self.gamma) * le partials["mesh", "chord"] = (mesh - gamma_chord).flatten() @@ -189,11 +193,11 @@ def compute_partials(self, inputs, partials): d_qc = (np.einsum("ij,i->ij", np.ones((ny, 3)), 1.0 - chord_dist)).flatten() nnq = (nx - 1) * ny * 3 partials["mesh", "in_mesh"][nn : nn + nnq] = np.tile(self.gamma * d_qc, nx - 1) - partials["mesh", "in_mesh"][nn + nnq :] = np.tile((1-self.gamma) * d_qc, nx - 1) + partials["mesh", "in_mesh"][nn + nnq :] = np.tile((1 - self.gamma) * d_qc, nx - 1) nnq = ny * 3 partials["mesh", "in_mesh"][nn - nnq : nn] += self.gamma * d_qc - partials["mesh", "in_mesh"][:nnq] += (1-self.gamma) * d_qc + partials["mesh", "in_mesh"][:nnq] += (1 - self.gamma) * d_qc class Sweep(om.ExplicitComponent): From 5036e9a9221eb0d7e676424d5ad866383d0c3d19 Mon Sep 17 00:00:00 2001 From: lucaeros Date: Tue, 9 May 2023 15:54:29 -0400 Subject: [PATCH 04/12] git pb --- .flake8 | 58 ------------------------------------------------------ .gitignore | 2 +- 2 files changed, 1 insertion(+), 59 deletions(-) diff --git a/.flake8 b/.flake8 index 295804467..627eef614 100644 --- a/.flake8 +++ b/.flake8 @@ -7,61 +7,3 @@ extend-exclude = openaerostruct/docs/_utils/patch.py, openaerostruct/utils/plot_*.py, -max-line-length = 120 - -extend-ignore = - # black - E203, - # too many leading '#' for block comment - E266, - # expected 2 blank lines, found 1 - E302, - # do not use mutable data structures for argument defaults (too many false positives) - B006, - # ===== TODO: to be fixed: - # invalid escape sequence, necessary for sphinx directives in docstrings but should switch to raw string - W605, - # line length, exceeded by some docstrings - E501, - # Function definition does not bind loop variable, happens everywhere in our code - B023, - # pydocstyle - D - -# Only add patterns here that are not included by the defaults of flake8 or other plugins -# extend-select = - -# flake8-docstrings -docstring-convention = numpy - -# flake8-rst-docstrings -rst-roles = - class, - func, - ref, - meth, - -rst-directives = - # Custom directives defined in the sphinx_mdolab_theme - embed-compare, - embed-bibtex, - embed-code, - embed-shell-cmd, - embed-n2, - -# mccabe complexity -# max-complexity = 10 - -# ignored files/directories -# we use exclude here and extend-exclude in repo-specific config files -# so that we can pass both to flake8 directly without needing to merge them first -exclude = - # No need to traverse the git directory - .git, - # There's no value in checking cache directories - __pycache__, - # The conf file is mostly autogenerated, ignore it - doc/conf.py, - # No need for init and setup files - __init__.py, - setup.py, diff --git a/.gitignore b/.gitignore index 933c0562b..786468a0a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,4 @@ src/adjoint/tempForward/ openaerostruct.egg-info/ .vscode *.plt -.pre-commit-config.yaml + From 1267dbc353aa5e259d39778389af0a7b83092a3f Mon Sep 17 00:00:00 2001 From: lucaeros Date: Tue, 9 May 2023 15:56:07 -0400 Subject: [PATCH 05/12] pb git --- .flake8 | 1 - .gitignore | 1 - 2 files changed, 2 deletions(-) diff --git a/.flake8 b/.flake8 index 627eef614..7dfa6ed49 100644 --- a/.flake8 +++ b/.flake8 @@ -6,4 +6,3 @@ extend-exclude = openaerostruct/docs/_utils/docutil.py, openaerostruct/docs/_utils/patch.py, openaerostruct/utils/plot_*.py, - diff --git a/.gitignore b/.gitignore index 786468a0a..8582ff81f 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,3 @@ src/adjoint/tempForward/ openaerostruct.egg-info/ .vscode *.plt - From 2c65a1df6e46b36f15a4f6383b7064f88791d97f Mon Sep 17 00:00:00 2001 From: lucaeros Date: Thu, 1 Jun 2023 15:55:58 -0400 Subject: [PATCH 06/12] add test chord scaling --- .../examples/rectangular_wing/opt_chord.py | 1 + openaerostruct/geometry/geometry_mesh.py | 14 +++++++----- .../geometry/geometry_mesh_transformations.py | 22 +++++++++---------- .../geometry/tests/test_geometry_mesh.py | 1 + .../test_geometry_mesh_transformations.py | 21 ++++++++++++++++++ 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/openaerostruct/examples/rectangular_wing/opt_chord.py b/openaerostruct/examples/rectangular_wing/opt_chord.py index 030ed202e..59038a152 100644 --- a/openaerostruct/examples/rectangular_wing/opt_chord.py +++ b/openaerostruct/examples/rectangular_wing/opt_chord.py @@ -57,6 +57,7 @@ "S_ref_type": "projected", # how we compute the wing area, # can be 'wetted' or 'projected' "chord_cp": np.ones(3), # Define chord using 3 B-spline cp's + "chord_scaling_pos": 0.25, # Define the chord scaling position. 0 is the leading edge, 1 is the trailing edge. # distributed along span "mesh": mesh, # Aerodynamic performance of the lifting surface at diff --git a/openaerostruct/geometry/geometry_mesh.py b/openaerostruct/geometry/geometry_mesh.py index 31a21d161..d08469103 100644 --- a/openaerostruct/geometry/geometry_mesh.py +++ b/openaerostruct/geometry/geometry_mesh.py @@ -77,17 +77,21 @@ def setup(self): # 2. Scale X val = np.ones(ny) + chord_scaling_pos = 0.25 # if no scaling position is specified : chord scaling w.r.t quarter of chord if "chord_cp" in surface: promotes = ["chord"] if "chord_scaling_pos" in surface: - gamma = surface["chord_scaling_pos"] - else: - gamma = 0.25 # if no scaling position is specified : chord scaling w.r.t quarter of chord + chord_scaling_pos = surface["chord_scaling_pos"] else: + if "chord_scaling_pos" in surface: + print("WARNING: chord_scaling_pos has been specified but no chord design variable available") promotes = [] - gamma = 0.25 - self.add_subsystem("scale_x", ScaleX(val=val, mesh_shape=mesh_shape, gamma=gamma), promotes_inputs=promotes) + self.add_subsystem( + "scale_x", + ScaleX(val=val, mesh_shape=mesh_shape, chord_scaling_pos=chord_scaling_pos), + promotes_inputs=promotes, + ) # 3. Sweep diff --git a/openaerostruct/geometry/geometry_mesh_transformations.py b/openaerostruct/geometry/geometry_mesh_transformations.py index e6ad44799..ea5f8ba5e 100644 --- a/openaerostruct/geometry/geometry_mesh_transformations.py +++ b/openaerostruct/geometry/geometry_mesh_transformations.py @@ -132,15 +132,15 @@ def initialize(self): self.options.declare("val", desc="Initial value for chord lengths") self.options.declare("mesh_shape", desc="Tuple containing mesh shape (nx, ny).") self.options.declare( - "gamma", + "chord_scaling_pos", default=0.25, - desc="float in [0.,1.] which indicates the chord fraction where to do the chord scaling. 1. is trailing edge, 0. is leading edge", + desc="float which indicates the chord fraction where to do the chord scaling. 1. is trailing edge, 0. is leading edge", ) def setup(self): mesh_shape = self.options["mesh_shape"] val = self.options["val"] - self.gamma = self.options["gamma"] + self.chord_scaling_pos = self.options["chord_scaling_pos"] self.add_input("chord", units="m", val=val) self.add_input("in_mesh", shape=mesh_shape, units="m") @@ -171,9 +171,9 @@ def compute(self, inputs, outputs): te = mesh[-1] le = mesh[0] - gamma_chord = self.gamma * te + (1 - self.gamma) * le + chord_pos = self.chord_scaling_pos * te + (1 - self.chord_scaling_pos) * le - outputs["mesh"] = np.einsum("ijk,j->ijk", mesh - gamma_chord, chord_dist) + gamma_chord + outputs["mesh"] = np.einsum("ijk,j->ijk", mesh - chord_pos, chord_dist) + chord_pos def compute_partials(self, inputs, partials): mesh = inputs["in_mesh"] @@ -181,9 +181,9 @@ def compute_partials(self, inputs, partials): te = mesh[-1] le = mesh[0] - gamma_chord = self.gamma * te + (1 - self.gamma) * le + chord_pos = self.chord_scaling_pos * te + (1 - self.chord_scaling_pos) * le - partials["mesh", "chord"] = (mesh - gamma_chord).flatten() + partials["mesh", "chord"] = (mesh - chord_pos).flatten() nx, ny, _ = mesh.shape nn = nx * ny * 3 @@ -192,12 +192,12 @@ def compute_partials(self, inputs, partials): d_qc = (np.einsum("ij,i->ij", np.ones((ny, 3)), 1.0 - chord_dist)).flatten() nnq = (nx - 1) * ny * 3 - partials["mesh", "in_mesh"][nn : nn + nnq] = np.tile(self.gamma * d_qc, nx - 1) - partials["mesh", "in_mesh"][nn + nnq :] = np.tile((1 - self.gamma) * d_qc, nx - 1) + partials["mesh", "in_mesh"][nn : nn + nnq] = np.tile(self.chord_scaling_pos * d_qc, nx - 1) + partials["mesh", "in_mesh"][nn + nnq :] = np.tile((1 - self.chord_scaling_pos) * d_qc, nx - 1) nnq = ny * 3 - partials["mesh", "in_mesh"][nn - nnq : nn] += self.gamma * d_qc - partials["mesh", "in_mesh"][:nnq] += (1 - self.gamma) * d_qc + partials["mesh", "in_mesh"][nn - nnq : nn] += self.chord_scaling_pos * d_qc + partials["mesh", "in_mesh"][:nnq] += (1 - self.chord_scaling_pos) * d_qc class Sweep(om.ExplicitComponent): diff --git a/openaerostruct/geometry/tests/test_geometry_mesh.py b/openaerostruct/geometry/tests/test_geometry_mesh.py index 633cf45e3..002a68d91 100644 --- a/openaerostruct/geometry/tests/test_geometry_mesh.py +++ b/openaerostruct/geometry/tests/test_geometry_mesh.py @@ -21,6 +21,7 @@ def test(self): # The way this is currently set up, we don't actually use the values here surface["twist_cp"] = np.zeros((5)) surface["chord_cp"] = np.zeros((5)) + surface["chord_scaling_pos"] = 0.25 surface["xshear_cp"] = np.zeros((5)) surface["yshear_cp"] = np.zeros((5)) surface["zshear_cp"] = np.zeros((5)) diff --git a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py index c2b0856f7..db28d2c10 100644 --- a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py +++ b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py @@ -132,6 +132,27 @@ def test_scalex_symmetry(self): check = prob.check_partials(compact_print=True, abs_err_tol=1e-5, rel_err_tol=1e-5) assert_check_partials(check, atol=1e-6, rtol=1e-6) + def test_scalex_chord_scaling_pos(self): + symmetry = False + mesh = get_mesh(symmetry) + + prob = om.Problem() + group = prob.model + + val = self.rng.random(NY) + for c in np.linspace(-1, 5, num=20): + comp = ScaleX(val=val, mesh_shape=mesh.shape, chord_scaling_pos=c) + group.add_subsystem("comp", comp) + + prob.setup() + + prob["comp.in_mesh"] = mesh + + prob.run_model() + + check = prob.check_partials(compact_print=True, abs_err_tol=1e-5, rel_err_tol=1e-5) + assert_check_partials(check, atol=1e-6, rtol=1e-6) + def test_sweep(self): symmetry = False mesh = get_mesh(symmetry) From 44d3409fb1dd029615abd4a3e333df0c37bfdfe5 Mon Sep 17 00:00:00 2001 From: lucaeros Date: Thu, 1 Jun 2023 16:15:13 -0400 Subject: [PATCH 07/12] change documentation --- openaerostruct/docs/user_reference/mesh_surface_dict.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/openaerostruct/docs/user_reference/mesh_surface_dict.rst b/openaerostruct/docs/user_reference/mesh_surface_dict.rst index e866cefc4..d1af3aa25 100644 --- a/openaerostruct/docs/user_reference/mesh_surface_dict.rst +++ b/openaerostruct/docs/user_reference/mesh_surface_dict.rst @@ -91,6 +91,14 @@ The surface dict will be provided to Groups, including ``Geometry``, ``AeroPoint - np.array([0, 5]) - deg - B-spline control points for twist distribution. Array convention is ``[wing tip, ..., root]`` in symmetry cases, and ``[tip, ..., root, ... tip]`` when ``symmetry = False``. + * - chord_cp + - np.array([0.1, 5]) + - m + - B-spline control points for chord distribution. Array convention is the same than ``twist_cp``. + * - chord_scaling_pos + - 0.25 + - + - Chord position at which the chord scaling factor is applied. 1 is the trailing edge, 0 is the leading edge. .. list-table:: Aerodynamics definitions :widths: 20 20 5 55 From d0e2cd31d6f4dd505cc7a41cbfcc622020794e3f Mon Sep 17 00:00:00 2001 From: lucaeros Date: Thu, 1 Jun 2023 18:01:54 -0400 Subject: [PATCH 08/12] corrected test --- .../test_geometry_mesh_transformations.py | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py index db28d2c10..4f5fe67eb 100644 --- a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py +++ b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py @@ -31,7 +31,13 @@ def get_mesh(symmetry): ny = (2 * NY - 1) if symmetry else NY # Create a dictionary to store options about the mesh - mesh_dict = {"num_y": ny, "num_x": NX, "wing_type": "CRM", "symmetry": symmetry, "num_twist_cp": NY} + mesh_dict = { + "num_y": ny, + "num_x": NX, + "wing_type": "CRM", + "symmetry": symmetry, + "num_twist_cp": NY, + } # Generate the aerodynamic mesh based on the previous dictionary mesh, twist_cp = generate_mesh(mesh_dict) @@ -140,18 +146,19 @@ def test_scalex_chord_scaling_pos(self): group = prob.model val = self.rng.random(NY) - for c in np.linspace(-1, 5, num=20): - comp = ScaleX(val=val, mesh_shape=mesh.shape, chord_scaling_pos=c) - group.add_subsystem("comp", comp) + chord_scaling_pos = self.rng.random(1) - prob.setup() + comp = ScaleX(val=val, mesh_shape=mesh.shape, chord_scaling_pos=chord_scaling_pos) + group.add_subsystem("comp", comp) - prob["comp.in_mesh"] = mesh + prob.setup() - prob.run_model() + prob["comp.in_mesh"] = mesh - check = prob.check_partials(compact_print=True, abs_err_tol=1e-5, rel_err_tol=1e-5) - assert_check_partials(check, atol=1e-6, rtol=1e-6) + prob.run_model() + + check = prob.check_partials(compact_print=True, abs_err_tol=1e-5, rel_err_tol=1e-5) + assert_check_partials(check, atol=1e-6, rtol=1e-6) def test_sweep(self): symmetry = False From f84553d81ae72347eb106c0c294b5295f738ea1d Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 7 Jun 2023 04:17:14 +0200 Subject: [PATCH 09/12] add warnings and check chord scaling --- openaerostruct/geometry/geometry_mesh.py | 3 ++- .../test_geometry_mesh_transformations.py | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/openaerostruct/geometry/geometry_mesh.py b/openaerostruct/geometry/geometry_mesh.py index d08469103..681f44e37 100644 --- a/openaerostruct/geometry/geometry_mesh.py +++ b/openaerostruct/geometry/geometry_mesh.py @@ -15,6 +15,7 @@ ShearZ, Rotate, ) +import warnings class GeometryMesh(om.Group): @@ -84,7 +85,7 @@ def setup(self): chord_scaling_pos = surface["chord_scaling_pos"] else: if "chord_scaling_pos" in surface: - print("WARNING: chord_scaling_pos has been specified but no chord design variable available") + warnings.warn("Chord_scaling_pos has been specified but no chord design variable available") promotes = [] self.add_subsystem( diff --git a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py index 4f5fe67eb..4d97c4294 100644 --- a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py +++ b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py @@ -4,7 +4,7 @@ import unittest import openmdao.api as om -from openmdao.utils.assert_utils import assert_check_partials +from openmdao.utils.assert_utils import assert_check_partials, assert_near_equal from openaerostruct.geometry.geometry_mesh_transformations import ( Taper, @@ -142,6 +142,7 @@ def test_scalex_chord_scaling_pos(self): symmetry = False mesh = get_mesh(symmetry) + # Test for random values of chord_scaling_pos, check derivatives prob = om.Problem() group = prob.model @@ -160,6 +161,23 @@ def test_scalex_chord_scaling_pos(self): check = prob.check_partials(compact_print=True, abs_err_tol=1e-5, rel_err_tol=1e-5) assert_check_partials(check, atol=1e-6, rtol=1e-6) + # Test for random values of chord_scaling_pos, check derivatives + prob = om.Problem() + group = prob.model + + val = self.rng.random(NY) + + comp = ScaleX(val=val, mesh_shape=mesh.shape, chord_scaling_pos=1) + group.add_subsystem("comp", comp) + + prob.setup() + + prob["comp.in_mesh"] = mesh + + prob.run_model() + # If chord_scaling_pos = 1, TE should not move + assert_near_equal(mesh[-1, :, :], prob["comp.mesh"][-1, :, :], tolerance=1e-10) + def test_sweep(self): symmetry = False mesh = get_mesh(symmetry) From 6cf93d1cb6facc14a11819a6201be65403be056a Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 7 Jun 2023 04:19:53 +0200 Subject: [PATCH 10/12] stack level --- openaerostruct/geometry/geometry_mesh.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openaerostruct/geometry/geometry_mesh.py b/openaerostruct/geometry/geometry_mesh.py index 681f44e37..03dcfd821 100644 --- a/openaerostruct/geometry/geometry_mesh.py +++ b/openaerostruct/geometry/geometry_mesh.py @@ -85,7 +85,9 @@ def setup(self): chord_scaling_pos = surface["chord_scaling_pos"] else: if "chord_scaling_pos" in surface: - warnings.warn("Chord_scaling_pos has been specified but no chord design variable available") + warnings.warn( + "Chord_scaling_pos has been specified but no chord design variable available", stacklevel=2 + ) promotes = [] self.add_subsystem( From 0f1f2d38194b26a71a3986a91a6d532a833760c3 Mon Sep 17 00:00:00 2001 From: lucaeros Date: Wed, 21 Jun 2023 09:55:24 -0400 Subject: [PATCH 11/12] change version init --- openaerostruct/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openaerostruct/__init__.py b/openaerostruct/__init__.py index fab833f38..b482efeb4 100644 --- a/openaerostruct/__init__.py +++ b/openaerostruct/__init__.py @@ -1 +1 @@ -__version__ = "2.6.1" +__version__ = "2.6.2" From 7a6191cb6c40d1c705decf8c77f4c6adbaa66728 Mon Sep 17 00:00:00 2001 From: Eytan Adler Date: Mon, 26 Jun 2023 11:24:06 -0400 Subject: [PATCH 12/12] Separate chord_scaling_pos test into two separate tests --- .../geometry/tests/test_geometry_mesh_transformations.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py index 4d97c4294..e75b1633b 100644 --- a/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py +++ b/openaerostruct/geometry/tests/test_geometry_mesh_transformations.py @@ -138,7 +138,7 @@ def test_scalex_symmetry(self): check = prob.check_partials(compact_print=True, abs_err_tol=1e-5, rel_err_tol=1e-5) assert_check_partials(check, atol=1e-6, rtol=1e-6) - def test_scalex_chord_scaling_pos(self): + def test_scalex_chord_scaling_pos_random(self): symmetry = False mesh = get_mesh(symmetry) @@ -161,7 +161,11 @@ def test_scalex_chord_scaling_pos(self): check = prob.check_partials(compact_print=True, abs_err_tol=1e-5, rel_err_tol=1e-5) assert_check_partials(check, atol=1e-6, rtol=1e-6) - # Test for random values of chord_scaling_pos, check derivatives + def test_scalex_chord_scaling_pos_trailing_edge(self): + symmetry = True + mesh = get_mesh(symmetry) + + # Test for chord_scaling_pos at trailing edge prob = om.Problem() group = prob.model @@ -175,6 +179,7 @@ def test_scalex_chord_scaling_pos(self): prob["comp.in_mesh"] = mesh prob.run_model() + # If chord_scaling_pos = 1, TE should not move assert_near_equal(mesh[-1, :, :], prob["comp.mesh"][-1, :, :], tolerance=1e-10)