Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Spherical Caps Included in Total Length #455

Merged
merged 9 commits into from
Nov 18, 2023
489 changes: 294 additions & 195 deletions docs/examples/SEB_liquid_motor.ipynb

Large diffs are not rendered by default.

41 changes: 30 additions & 11 deletions rocketpy/motors/tank_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,28 +369,47 @@ def __init__(self, radius, height, spherical_caps=False, geometry_dict=dict()):
height : float
Height of the cylindrical tank, in meters.
spherical_caps : bool, optional
If True, the tank will have spherical caps. The default is False.
If True, the tank will have spherical caps at the top and bottom
with the same radius as the cylindrical part. If False, the tank
will have flat caps at the top and bottom. Defaults to False.
geometry_dict : dict, optional
Dictionary containing the geometry of the tank. See TankGeometry.
"""
super().__init__(geometry_dict)
self.height = height
self.has_caps = False
self.add_geometry((-height / 2, height / 2), radius)
self.add_spherical_caps() if spherical_caps else None
if spherical_caps:
self.add_geometry((-height / 2 + radius, height / 2 - radius), radius)
self.add_spherical_caps()
else:
self.add_geometry((-height / 2, height / 2), radius)

def add_spherical_caps(self):
"""
Adds spherical caps to the tank. The caps are added at the bottom
and at the top of the tank. If the tank already has caps, it raises a
ValueError.
"""
and at the top of the tank with the same radius as the cylindrical
part. The height is not modified, meaning that the total volume of
the tank will decrease.
"""
print(
"Warning: Adding spherical caps to the tank will not modify the "
+ f"total height of the tank {self.height} m. "
+ "Its cylindrical portion height will be reduced to "
+ f"{self.height - 2*self.radius(0)} m."
)

if not self.has_caps:
radius = self.radius(0)
height = self.total_height
bottom_cap_range = (-height / 2 - radius, -height / 2)
upper_cap_range = (height / 2, height / 2 + radius)
bottom_cap_radius = lambda h: (radius**2 - (h + height / 2) ** 2) ** 0.5
upper_cap_radius = lambda h: (radius**2 - (h - height / 2) ** 2) ** 0.5
height = self.height
bottom_cap_range = (-height / 2, -height / 2 + radius)
upper_cap_range = (height / 2 - radius, height / 2)

def bottom_cap_radius(h):
return abs(radius**2 - (h + (height / 2 - radius)) ** 2) ** 0.5

def upper_cap_radius(h):
return abs(radius**2 - (h - (height / 2 - radius)) ** 2) ** 0.5

self.add_geometry(bottom_cap_range, bottom_cap_radius)
self.add_geometry(upper_cap_range, upper_cap_radius)
self.has_caps = True
Expand Down
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ def pressurant_tank(pressurant_fluid):
rocketpy.MassBasedTank
An object of the CylindricalTank class.
"""
geometry = CylindricalTank(0.135 / 2, 0.846, spherical_caps=True)
geometry = CylindricalTank(0.135 / 2, 0.981, spherical_caps=True)
pressurant_tank = MassBasedTank(
name="Pressure Tank",
geometry=geometry,
Expand Down Expand Up @@ -401,7 +401,7 @@ def fuel_tank(fuel_fluid, fuel_pressurant):
-------
rocketpy.UllageBasedTank
"""
geometry = CylindricalTank(0.0744, 0.658, spherical_caps=True)
geometry = CylindricalTank(0.0744, 0.8068, spherical_caps=True)
ullage = (
-Function("data/SEBLM/test124_Propane_Volume.csv") * 1e-3
+ geometry.total_volume
Expand Down Expand Up @@ -435,7 +435,7 @@ def oxidizer_tank(oxidizer_fluid, oxidizer_pressurant):
-------
rocketpy.UllageBasedTank
"""
geometry = CylindricalTank(0.0744, 0.658, spherical_caps=True)
geometry = CylindricalTank(0.0744, 0.8068, spherical_caps=True)
ullage = (
-Function("data/SEBLM/test124_Lox_Volume.csv") * 1e-3 + geometry.total_volume
)
Expand Down
30 changes: 16 additions & 14 deletions tests/test_tank.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
TankGeometry,
)

pressurant_params = (0.135 / 2, 0.846)
fuel_params = (0.0744, 0.658)
oxidizer_params = (0.0744, 0.658)
pressurant_params = (0.135 / 2, 0.981)
fuel_params = (0.0744, 0.8068)
oxidizer_params = (0.0744, 0.8068)

parametrize_fixtures = pytest.mark.parametrize(
"params",
Expand All @@ -33,7 +33,7 @@ def test_tank_bounds(params, request):
tank, (expected_radius, expected_height) = params
tank = request.getfixturevalue(tank)

expected_total_height = expected_height + 2 * expected_radius
expected_total_height = expected_height

assert tank.geometry.radius(0) == pytest.approx(expected_radius, abs=1e-6)
assert tank.geometry.total_height == pytest.approx(expected_total_height, abs=1e-6)
Expand All @@ -45,8 +45,8 @@ def test_tank_coordinates(params, request):
tank, (radius, height) = params
tank = request.getfixturevalue(tank)

expected_bottom = -(height / 2 + radius)
expected_top = height / 2 + radius
expected_bottom = -height / 2
expected_top = height / 2

assert tank.geometry.bottom == pytest.approx(expected_bottom, abs=1e-6)
assert tank.geometry.top == pytest.approx(expected_top, abs=1e-6)
Expand All @@ -60,7 +60,9 @@ def test_tank_total_volume(params, request):
tank, (radius, height) = params
tank = request.getfixturevalue(tank)

expected_total_volume = np.pi * radius**2 * height + 4 / 3 * np.pi * radius**3
expected_total_volume = (
np.pi * radius**2 * (height - 2 * radius) + 4 / 3 * np.pi * radius**3
)

assert tank.geometry.total_volume == pytest.approx(expected_total_volume, abs=1e-6)

Expand All @@ -73,9 +75,9 @@ def test_tank_volume(params, request):
tank, (radius, height) = params
tank = request.getfixturevalue(tank)

total_height = height + 2 * radius
bottom = -(height / 2 + radius)
top = height / 2 + radius
total_height = height
bottom = -height / 2
top = height / 2

expected_volume = tank_volume_function(radius, total_height, bottom)

Expand All @@ -91,8 +93,8 @@ def test_tank_centroid(params, request):
tank, (radius, height) = params
tank = request.getfixturevalue(tank)

total_height = height + 2 * radius
bottom = -(height / 2 + radius)
total_height = height
bottom = -height / 2

expected_centroid = tank_centroid_function(radius, total_height, bottom)

Expand All @@ -111,8 +113,8 @@ def test_tank_inertia(params, request):
tank, (radius, height) = params
tank = request.getfixturevalue(tank)

total_height = height + 2 * radius
bottom = -(height / 2 + radius)
total_height = height
bottom = -height / 2

expected_inertia = tank_inertia_function(radius, total_height, bottom)

Expand Down
Loading