Skip to content

Commit

Permalink
Merge pull request #484 from RocketPy-Team/bug/tanks-overfill
Browse files Browse the repository at this point in the history
ENH: Prevent out of bounds Tanks from Instantiation
  • Loading branch information
MateusStano authored Nov 24, 2023
2 parents 3434ae9 + dab946d commit 553c0f7
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ You can install this version by running `pip install rocketpy==1.1.1`
### Added

- DOC: Added this changelog file [#472](https://github.com/RocketPy-Team/RocketPy/pull/472)
- ENH: Prevent out of bounds Tanks from Instantiation #484 [#484](https://github.com/RocketPy-Team/RocketPy/pull/484)

### Fixed

Expand Down
119 changes: 97 additions & 22 deletions rocketpy/motors/tank.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ def __init__(self, name, geometry, flux_time, liquid, gas, discretize=100):
# Initialize plots and prints object
self.prints = _TankPrints(self)
self.plots = _TankPlots(self)
return None

@property
def flux_time(self):
Expand Down Expand Up @@ -410,6 +409,82 @@ def inertia(self):
"""
return self.liquid_inertia + self.gas_inertia

def _check_volume_bounds(self):
"""Checks if the tank is overfilled or underfilled. Raises a ValueError
if either the `gas_volume` or `liquid_volume` are out of tank geometry
bounds.
"""

def overfill_volume_exception(param_name, param):
raise ValueError(

Check warning on line 419 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L419

Added line #L419 was not covered by tests
f"The tank '{self.name}' is overfilled. The {param_name} is "
+ "greater than the total volume of the tank.\n\t\t"
+ "Try increasing the tank height and check out the fluid density "
+ "values.\n\t\t"
+ f"The {param_name} is {param.max:.3f} m³ at "
+ f"{param.x_array[np.argmax(param.y_array)]:.3f} s.\n\t\t"
+ f"The tank total volume is {self.geometry.total_volume:.3f} m³."
)

def underfill_volume_exception(param_name, param):
raise ValueError(

Check warning on line 430 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L430

Added line #L430 was not covered by tests
f"The tank '{self.name}' is underfilled. The {param_name} is "
+ "negative.\n\t\t"
+ "Try increasing input fluid quantities and check out the fluid "
+ "density values.\n\t\t"
+ f"The {param_name} is {param.min:.3f} m³ at "
+ f"{param.x_array[np.argmin(param.y_array)]:.3f} s.\n\t\t"
+ f"The tank total volume is {self.geometry.total_volume:.3f} m³."
)

for name, volume in [
("gas volume", self.gas_volume),
("liquid volume", self.liquid_volume),
]:
if (volume > self.geometry.total_volume + 1e-6).any():
overfill_volume_exception(name, volume)

Check warning on line 445 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L445

Added line #L445 was not covered by tests
elif (volume < -1e-6).any():
underfill_volume_exception(name, volume)

Check warning on line 447 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L447

Added line #L447 was not covered by tests

def _check_height_bounds(self):
"""Checks if the tank is overfilled or underfilled. Raises a ValueError
if either the `gas_height` or `liquid_height` are out of tank geometry
bounds.
"""
top_tolerance = self.geometry.top + 1e-4
bottom_tolerance = self.geometry.bottom - 1e-4

def overfill_height_exception(param_name, param):
raise ValueError(

Check warning on line 458 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L458

Added line #L458 was not covered by tests
f"The tank '{self.name}' is overfilled. "
+ f"The {param_name} is above the tank top.\n\t\t"
+ "Try increasing the tank height and check out the fluid density "
+ "values.\n\t\t"
+ f"The {param_name} is {param.max:.3f} m above the tank top "
+ f"at {param.x_array[np.argmax(param.y_array)]:.3f} s.\n\t\t"
+ f"The tank top is at {self.geometry.top:.3f} m."
)

def underfill_height_exception(param_name, param):
raise ValueError(

Check warning on line 469 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L469

Added line #L469 was not covered by tests
f"The tank '{self.name}' is underfilled. "
+ f"The {param_name} is below the tank bottom.\n\t\t"
+ "Try increasing input fluid quantities and check out the fluid "
+ "density values.\n\t\t"
+ f"The {param_name} is {param.min:.3f} m below the tank bottom "
+ f"at {param.x_array[np.argmin(param.y_array)]:.3f} s.\n\t\t"
+ f"The tank bottom is at {self.geometry.bottom:.3f} m."
)

for name, height in [
("gas height", self.gas_height),
("liquid height", self.liquid_height),
]:
if (height > top_tolerance).any():
overfill_height_exception(name, height)

Check warning on line 484 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L484

Added line #L484 was not covered by tests
elif (height < bottom_tolerance).any():
underfill_height_exception(name, height)

Check warning on line 486 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L486

Added line #L486 was not covered by tests

def draw(self):
"""Draws the tank geometry."""
self.plots.draw()
Expand Down Expand Up @@ -535,7 +610,10 @@ def __init__(

# Discretize input flow if needed
self.discretize_flow() if discretize else None
return None

# Check if the tank is overfilled or underfilled
self._check_volume_bounds()
self._check_height_bounds()

@funcify_method("Time (s)", "Mass (kg)")
def fluid_mass(self):
Expand Down Expand Up @@ -814,15 +892,9 @@ def __init__(
# Discretize input if needed
self.discretize_ullage() if discretize else None

# Check if the ullage is within bounds
if (self.ullage > self.geometry.total_volume).any():
raise ValueError(
"The ullage volume is out of bounds. It is greater than the "
+ "total volume of the tank."
)
if (self.ullage < 0).any():
raise ValueError("The ullage volume is out of bounds. It is negative.")
return None
# Check if the tank is overfilled or underfilled
self._check_volume_bounds()
self._check_height_bounds()

@funcify_method("Time (s)", "Mass (kg)")
def fluid_mass(self):
Expand Down Expand Up @@ -862,7 +934,9 @@ def fluid_volume(self):
Function
Volume of the fluid as a function of time.
"""
return self.geometry.total_volume
return Function(self.geometry.total_volume).set_discrete_based_on_model(

Check warning on line 937 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L937

Added line #L937 was not covered by tests
self.gas_volume
)

@funcify_method("Time (s)", "Volume (m³)")
def liquid_volume(self):
Expand Down Expand Up @@ -1012,13 +1086,9 @@ def __init__(
# Discretize input if needed
self.discretize_liquid_height() if discretize else None

# Check if the liquid level is within bounds
if (self.liquid_level > self.geometry.top).any():
raise ValueError(
"The liquid level is out of bounds. It is greater than the tank top."
)
if (self.liquid_level < self.geometry.bottom).any():
raise ValueError("The liquid level is out of bounds. It is negative.")
# Check if the tank is overfilled or underfilled
self._check_height_bounds()
self._check_volume_bounds()

@funcify_method("Time (s)", "Mass (kg)")
def fluid_mass(self):
Expand Down Expand Up @@ -1062,7 +1132,7 @@ def fluid_volume(self):
Volume of the fluid as a function of time.
"""
volume = self.gas_volume + self.liquid_volume
diff = abs(volume - self.geometry.total_volume)
diff = volume - self.geometry.total_volume

Check warning on line 1135 in rocketpy/motors/tank.py

View check run for this annotation

Codecov / codecov/patch

rocketpy/motors/tank.py#L1135

Added line #L1135 was not covered by tests
if (diff > 1e-6).any():
raise ValueError(
"The `fluid_volume`, defined as the sum of `gas_volume` and "
Expand Down Expand Up @@ -1096,9 +1166,10 @@ def gas_volume(self):
Volume of the gas as a function of time.
"""
# TODO: there's a bug on the gas_center_of_mass is I don't discretize here
func = Function(self.geometry.total_volume)
func = Function(self.geometry.total_volume).set_discrete_based_on_model(
self.liquid_volume
)
func -= self.liquid_volume
func.set_discrete_based_on_model(self.liquid_volume)
return func

@funcify_method("Time (s)", "Height (m)")
Expand Down Expand Up @@ -1230,6 +1301,10 @@ def __init__(
# Discretize input if needed
self.discretize_masses() if discretize else None

# Check if the tank is overfilled or underfilled
self._check_volume_bounds()
self._check_height_bounds()

@funcify_method("Time (s)", "Mass (kg)")
def fluid_mass(self):
"""
Expand Down

0 comments on commit 553c0f7

Please sign in to comment.