Skip to content

Commit

Permalink
Support for Numpy 2.1 and OpenMDAO 3.35 (#450)
Browse files Browse the repository at this point in the history
* Add support for numpy2 and OpenMDAO 3.35

* Fix b-spline interpolation for mid_panel x_interp points. Compatible with openMDAO 3.35 and later

* Bump OAS version and required OpenMDAO version. Update docs

* Removed openmdao version constraint

* also removed numpy version constraint

* Add support for numpy2 and OpenMDAO 3.35

* Fix b-spline interpolation for mid_panel x_interp points. Compatible with openMDAO 3.35 and later

* Bump OAS version and required OpenMDAO version. Update docs

* Removed openmdao version constraint

* also removed numpy version constraint

* Update b-spline component for structures and retrain all tests

* Flake 8 fix

* Docs updates

* Change MPhys capitalization

---------

Co-authored-by: Shugo Kaneko <[email protected]>
Co-authored-by: Eytan Adler <[email protected]>
  • Loading branch information
3 people authored Jan 17, 2025
1 parent f79f9cc commit b5ac877
Show file tree
Hide file tree
Showing 29 changed files with 78 additions and 54 deletions.
1 change: 1 addition & 0 deletions .github/build_real.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
set -e
sed -i '/mphys/d' "$HOME/.config/pip/constraints.txt" # Remove the pip constraint on the mphys version
sed -i '/numpy/d; /openmdao/d' "$HOME/.config/pip/constraints.txt" # Remove the pip constraint on the numpy and openmdao version
pip install .[testing,mphys]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ The oldest and latest versions of the dependencies that we test regularly are th
| Python | 3.8 | 3.11 |
| NumPy | 1.20 | latest |
| SciPy | 1.6.0 | latest |
| OpenMDAO | 3.15 | latest |
| OpenMDAO | 3.35 | latest |
| Matplotlib | latest | latest |
| MPhys (optional) | 2.0.0 | latest |
| pyGeo (optional) | 1.6.0 | latest |
Expand Down
2 changes: 1 addition & 1 deletion openaerostruct/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.9.1"
__version__ = "2.10.0"
2 changes: 1 addition & 1 deletion openaerostruct/aerodynamics/eval_mtx.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ def setup(self):
(num_eval_points, nx - 1, ny - 1, 3, 3)
)
aic_base = np.einsum("ijkl,m->ijklm", vel_mtx_indices, np.ones(3, int))
aic_len = np.sum(np.product(aic_base.shape))
aic_len = np.sum(np.prod(aic_base.shape))

if ground_effect:
# mirrored surface along the x mesh direction
Expand Down
5 changes: 4 additions & 1 deletion openaerostruct/docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ The oldest and latest versions of the dependencies that we test regularly are th
- 1.6.0
- latest
* - OpenMDAO
- 3.15
- 3.35
- latest
* - Matplotlib
- latest
Expand All @@ -55,6 +55,9 @@ The oldest and latest versions of the dependencies that we test regularly are th
* - OpenVSP (optional)
- 3.27.1
- 3.27.1
* - MPhys (optional)
- 2.0
- latest

If you are unfamiliar with OpenMDAO and wish to modify the internals of OpenAeroStruct, you should examine the OpenMDAO documentation at http://openmdao.org/twodocs/versions/latest/index.html. The tutorials provided with OpenMDAO are helpful to understand the basics of using OpenMDAO to solve an optimization problem.

Expand Down
10 changes: 8 additions & 2 deletions openaerostruct/geometry/geometry_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ def setup(self):
comp = self.add_subsystem(
"t_over_c_bsp",
om.SplineComp(
method="bsplines", x_interp_val=x_interp, num_cp=n_cp, interp_options={"order": min(n_cp, 4)}
method="bsplines",
x_interp_val=x_interp,
num_cp=n_cp,
interp_options={"order": min(n_cp, 4), "x_cp_start": 0.0, "x_cp_end": 1.0},
),
promotes_inputs=["t_over_c_cp"],
promotes_outputs=["t_over_c"],
Expand Down Expand Up @@ -110,7 +113,10 @@ def setup(self):
comp = self.add_subsystem(
"t_over_c_bsp",
om.SplineComp(
method="bsplines", x_interp_val=x_interp, num_cp=n_cp, interp_options={"order": min(n_cp, 4)}
method="bsplines",
x_interp_val=x_interp,
num_cp=n_cp,
interp_options={"order": min(n_cp, 4), "x_cp_start": 0, "x_cp_end": 1},
),
promotes_inputs=["t_over_c_cp"],
promotes_outputs=["t_over_c"],
Expand Down
10 changes: 8 additions & 2 deletions openaerostruct/structures/tube_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ def setup(self):
comp = self.add_subsystem(
"thickness_bsp",
om.SplineComp(
method="bsplines", x_interp_val=x_interp, num_cp=n_cp, interp_options={"order": min(n_cp, 4)}
method="bsplines",
x_interp_val=x_interp,
num_cp=n_cp,
interp_options={"order": min(n_cp, 4), "x_cp_start": 0, "x_cp_end": 1},
),
promotes_inputs=["thickness_cp"],
promotes_outputs=["thickness"],
Expand All @@ -37,7 +40,10 @@ def setup(self):
comp = self.add_subsystem(
"radius_bsp",
om.SplineComp(
method="bsplines", x_interp_val=x_interp, num_cp=n_cp, interp_options={"order": min(n_cp, 4)}
method="bsplines",
x_interp_val=x_interp,
num_cp=n_cp,
interp_options={"order": min(n_cp, 4), "x_cp_start": 0, "x_cp_end": 1},
),
promotes_inputs=["radius_cp"],
promotes_outputs=["radius"],
Expand Down
10 changes: 8 additions & 2 deletions openaerostruct/structures/wingbox_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ def setup(self):
comp = self.add_subsystem(
"spar_thickness_bsp",
om.SplineComp(
method="bsplines", x_interp_val=x_interp, num_cp=n_cp, interp_options={"order": min(n_cp, 4)}
method="bsplines",
x_interp_val=x_interp,
num_cp=n_cp,
interp_options={"order": min(n_cp, 4), "x_cp_start": 0, "x_cp_end": 1},
),
promotes_inputs=["spar_thickness_cp"],
promotes_outputs=["spar_thickness"],
Expand All @@ -35,7 +38,10 @@ def setup(self):
comp = self.add_subsystem(
"skin_thickness_bsp",
om.SplineComp(
method="bsplines", x_interp_val=x_interp, num_cp=n_cp, interp_options={"order": min(n_cp, 4)}
method="bsplines",
x_interp_val=x_interp,
num_cp=n_cp,
interp_options={"order": min(n_cp, 4), "x_cp_start": 0, "x_cp_end": 1},
),
promotes_inputs=["skin_thickness_cp"],
promotes_outputs=["skin_thickness"],
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
package_data={"openaerostruct": ["tests/*.py", "*/tests/*.py", "*/*/tests/*.py"]},
install_requires=[
# Remember to update the oldest versions in the GitHub Actions build, the readme, and in docs/installation.rst
"openmdao>=3.15",
"openmdao>=3.35",
"numpy>=1.20",
"scipy>=1.6.0",
"matplotlib",
Expand Down
5 changes: 4 additions & 1 deletion tests/aerodynamics_tests/test_wave_drag.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ def test(self):
comp = group.add_subsystem(
"t_over_c_bsp",
om.SplineComp(
method="bsplines", x_interp_val=x_interp, num_cp=n_cp, interp_options={"order": min(n_cp, 4)}
method="bsplines",
x_interp_val=x_interp,
num_cp=n_cp,
interp_options={"order": min(n_cp, 4)},
),
promotes_inputs=["t_over_c_cp"],
promotes_outputs=["t_over_c"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def test(self):
prob.run_driver()

assert_near_equal(prob["aero_point_0.CL"][0], 0.46419154063077483, 1e-6)
assert_near_equal(prob["aero_point_0.CD"][0], 0.020863555824806052, 1e-6)
assert_near_equal(prob["aero_point_0.CD"][0], 0.020404720588811737, 1e-6)
assert_near_equal(prob["aero_point_0.CM"][1], -1.8595708973535592, 1e-6)


Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/test_aero_opt_wavedrag.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def test(self):
assert_opt_successful(self, optResult)

assert_near_equal(prob["aero_point_0.CL"][0], 0.5, 1e-6)
assert_near_equal(prob["aero_point_0.CD"][0], 0.021353004050991248, 1e-6)
assert_near_equal(prob["aero_point_0.CD"][0], 0.020825781122528385, 1e-6)
assert_near_equal(prob["aero_point_0.CM"][1], -2.0819892547514067, 1e-6)


Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/test_aerostruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def test(self):
assert_near_equal(prob["AS_point_0.beta"], 0.0)
assert_opt_successful(self, optResult)

assert_near_equal(prob["AS_point_0.fuelburn"][0], 92523.945549167, 1e-8)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 92523.9636052887, 1e-8)


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_aerostruct_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ def test(self):

prob.run_model()

assert_near_equal(prob["AS_point_0.fuelburn"][0], 263398.25938918366, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.6462808405237332, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 241347.34494621187, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.7040800097095121, 1e-5)


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_aerostruct_analysis_Sref.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ def test(self):

prob.run_model()

assert_near_equal(prob["AS_point_0.CL"][0], 1.6210175228727655, 1e-6)
assert_near_equal(prob["AS_point_0.CM"][1], -1.8365760768848112, 1e-5)
assert_near_equal(prob["AS_point_0.CL"][0], 1.619784221965875, 1e-6)
assert_near_equal(prob["AS_point_0.CM"][1], -2.0008904315028193, 1e-5)


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ def test(self):

prob.run_model()

assert_near_equal(prob["AS_point_0.fuelburn"][0], 224121.12881258246, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.9083682371351329, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 205383.27093443452, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.9867712621195601, 1e-5)


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_aerostruct_engine_thrusts.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ def test(self):
print(prob["AS_point_0.fuelburn"][0])
print(prob["AS_point_0.CM"][1])

assert_near_equal(prob["AS_point_0.fuelburn"][0], 263992.6780138112, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.6438933659444002, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 241937.85848709388, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.7013413978098743, 1e-5)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/test_aerostruct_groundeffect.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def test(self):
optResult = prob.run_driver()
assert_opt_successful(self, optResult)
# the fuel burn should be less in ground effect
assert_near_equal(prob["AS_point_0.fuelburn"][0], 86980.04655202407, 1e-6)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 86980.21117717, 1e-6)
totals = prob.check_totals(
of=["AS_point_0.L_equals_W", "AS_point_0.fuelburn", "AS_point_0.wing_perf.failure"],
wrt=["wing.twist_cp", "alpha", "height_agl"],
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_aerostruct_point_loads.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ def test(self):

prob.run_model()

assert_near_equal(prob["AS_point_0.fuelburn"][0], 264106.7825178142, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.6436834908660709, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 242051.20185901612, 1e-4)
assert_near_equal(prob["AS_point_0.CM"][1], -0.7010846868817897, 1e-5)


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,8 @@ def test(self):

prob.run_model()

assert_near_equal(prob["AS_point_0.fuelburn"][0], 87333.56998786073, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 34500.40422127632, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 85296.25551779529, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 29707.645593713547, 1e-5)


if __name__ == "__main__":
Expand Down
6 changes: 3 additions & 3 deletions tests/integration_tests/test_aerostruct_wingbox_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,9 @@ def test(self):
print(prob["wing.structural_mass"][0] / 1.25)
print(prob["AS_point_0.wing_perf.failure"][0])

assert_near_equal(prob["AS_point_0.fuelburn"][0], 87760.55423816708, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 34500.40422127632, 1e-5)
assert_near_equal(prob["AS_point_0.wing_perf.failure"][0], -0.15727437869018163, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 87095.16845081086, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 29707.645593713547, 1e-5)
assert_near_equal(prob["AS_point_0.wing_perf.failure"][0], 0.004148750437858817, 1e-5)


if __name__ == "__main__":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,8 @@ def test(self):

assert_opt_successful(self, optResult)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 76869.3858256513, 1e-4)
assert_near_equal(prob["wing.structural_mass"][0], 14523.135605406405, 1e-4)
assert_near_equal(prob["fuel_vol_delta.fuel_vol_delta"][0], 42.99371350246894, 1e-4)
assert_near_equal(prob["wing.structural_mass"][0], 14520.819967195273, 1e-4)
assert_near_equal(prob["fuel_vol_delta.fuel_vol_delta"][0], 43.02081603846062, 1e-4)
assert_near_equal(prob["AS_point_0.CL"][0], 0.5, 1e-5)


Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/test_aerostruct_wingbox_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ def test(self):

prob.run_driver()
assert_near_equal(prob["AS_point_0.fuelburn"][0], 79151.03928720397, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0] / 1.25, 13387.705394088985, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0] / 1.25, 13388.445732877735, 1e-5)
assert_near_equal(prob["wing.geometry.span"][0], 60.0, 1e-5)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,8 @@ def test(self):
optResult = prob.run_driver()

assert_opt_successful(self, optResult)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 85374.45357945036, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 13048.465090719292, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 85400.83793743863, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 13149.34611487464, 1e-5)
assert_near_equal(prob["AS_point_0.CL"][0], 0.5, 1e-5)


Expand Down
19 changes: 9 additions & 10 deletions tests/integration_tests/test_multipoint_parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

import unittest
from openmdao.utils.assert_utils import assert_near_equal
from openmdao.utils.assert_utils import assert_near_equal, assert_check_totals

try:
from petsc4py import PETSc # noqa: F401
Expand Down Expand Up @@ -379,7 +379,6 @@ def test_multipoint_MPI(self):

# compute derivatives
start_time = time.time()
totals = prob.compute_totals()
derivs_time = time.time() - start_time

print("I am processor", MPI.COMM_WORLD.rank, ", finished run_model and compute_totals")
Expand All @@ -392,17 +391,17 @@ def test_multipoint_MPI(self):
# OpenMDAO versions before 3.31 use absolute names as dictionary keys, but versions after
# use user facing (promoted) names. Handle both cases here.
try:
deriv_fuel_sum_spar_thickness = totals[("fuel_sum.fuel_sum", "wing.spar_thickness_cp")]
deriv_fuel_sum_spar_thickness = prob.check_totals(
of=["fuel_sum.fuel_sum"], wrt=["wing.spar_thickness_cp"], compact_print=True
)
except KeyError:
deriv_fuel_sum_spar_thickness = totals[("fuel_sum", "wing.spar_thickness_cp")]
deriv_fuel_sum_spar_thickness = prob.check_totals(
of=["fuel_sum"], wrt=["wing.spar_thickness_cp"], compact_print=True
)

assert_near_equal(MPI.COMM_WORLD.size, 2, 1e-8)
assert_near_equal(prob.get_val("fuel_sum", units="kg"), 5663.04182905, 1e-5)
assert_near_equal(
deriv_fuel_sum_spar_thickness,
np.array([[1467.2504797, 2271.82835456, 3133.0901236, 5247.87365798]]),
1e-5,
)
assert_near_equal(prob.get_val("fuel_sum", units="kg"), 5646.50827504, 1e-5)
assert_check_totals(deriv_fuel_sum_spar_thickness, rtol=1e-4, atol=1.0)


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_multipoint_wingbox_aerostruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,8 @@ def test(self):

assert_opt_successful(self, optResult)

assert_near_equal(prob["AS_point_0.fuelburn"][0], 87326.95014538494, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 32947.84007488438, 1e-5)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 87326.71090049665, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0], 32943.97274107966, 1e-5)
assert_near_equal(prob["AS_point_0.CL"][0], 0.5, 1e-5)
assert_near_equal(prob["AS_point_1.L_equals_W"][0], 0.0, 1e-5)

Expand Down
6 changes: 3 additions & 3 deletions tests/integration_tests/test_scaneagle.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,9 @@ def test_opt(self):
self.prob.run_driver()

assert_near_equal(self.prob["AS_point_0.fuelburn"][0], 4.518756027353296, 1e-5)
assert_near_equal(self.prob["wing.twist_cp"], np.array([2.74161203, 12.22389255, 5.0]), 1e-5)
assert_near_equal(self.prob["wing.sweep"][0], 18.909083171987344, 1e-5)
assert_near_equal(self.prob["alpha"][0], 1.4756577579439902, 1e-5)
assert_near_equal(self.prob["wing.twist_cp"], np.array([2.74343152, 12.2239185, 5.0]), 1e-5)
assert_near_equal(self.prob["wing.sweep"][0], 18.908583449616266, 1e-5)
assert_near_equal(self.prob["alpha"][0], 1.475153325082263, 1e-5)

def test_totals(self):
# Set up the problem
Expand Down
2 changes: 1 addition & 1 deletion tests/integration_tests/test_wingbox_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ def test(self):
assert_check_partials(data, atol=1e20, rtol=1e-6)

prob.run_driver()
assert_near_equal(prob["wing.structural_mass"], 16675.586037621928, 1e-6)
assert_near_equal(prob["wing.structural_mass"], 16932.20046986, 1e-6)


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/test_wingbox_distributed_fuel.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,8 +443,8 @@ def test(self):
print(prob["AS_point_0.fuelburn"][0])
print(prob["wing.structural_mass"][0] / 1.25)

assert_near_equal(prob["AS_point_0.fuelburn"][0], 75973.2666251404, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0] / 1.25, 12486.89671978072, 1e-4)
assert_near_equal(prob["AS_point_0.fuelburn"][0], 75974.26940153482, 1e-5)
assert_near_equal(prob["wing.structural_mass"][0] / 1.25, 12487.980814567598, 1e-4)


if __name__ == "__main__":
Expand Down

0 comments on commit b5ac877

Please sign in to comment.