diff --git a/CHANGELOG.md b/CHANGELOG.md index 15cb0f7dd..876de3847 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,11 +32,11 @@ Attention: The newest changes should be on top --> ### Added -- DOC: ASTRA Flight Example [#770](https://github.com/RocketPy-Team/RocketPy/pull/770)) +- DOC: ASTRA Flight Example [#770](https://github.com/RocketPy-Team/RocketPy/pull/770) ### Changed -- +- MNT: EmptyMotor class inherits from Motor(ABC) [#779](https://github.com/RocketPy-Team/RocketPy/pull/779) ### Fixed diff --git a/rocketpy/motors/__init__.py b/rocketpy/motors/__init__.py index 85baae930..73f49633c 100644 --- a/rocketpy/motors/__init__.py +++ b/rocketpy/motors/__init__.py @@ -1,7 +1,8 @@ +from .empty_motor import EmptyMotor from .fluid import Fluid from .hybrid_motor import HybridMotor from .liquid_motor import LiquidMotor -from .motor import EmptyMotor, GenericMotor, Motor +from .motor import GenericMotor, Motor from .solid_motor import SolidMotor from .tank import ( LevelBasedTank, diff --git a/rocketpy/motors/empty_motor.py b/rocketpy/motors/empty_motor.py new file mode 100644 index 000000000..4e844472b --- /dev/null +++ b/rocketpy/motors/empty_motor.py @@ -0,0 +1,78 @@ +from rocketpy.mathutils import Function, funcify_method +from rocketpy.motors.motor import Motor + + +class EmptyMotor(Motor): + """Class that represents an empty motor with no mass and no thrust.""" + + def __init__(self): + """Initializes an empty motor with no mass and no thrust.""" + + super().__init__( + thrust_source=0, + dry_inertia=(0, 0, 0), + nozzle_radius=0, + center_of_dry_mass_position=0, + dry_mass=0, + nozzle_position=0, + burn_time=1, + reshape_thrust_curve=False, + interpolation_method="linear", + coordinate_system_orientation="nozzle_to_combustion_chamber", + ) + + # Mass properties + self.propellant_mass = Function(0, "Time (s)", "Propellant Mass (kg)") + self.total_mass = Function(0, "Time (s)", "Total Mass (kg)") + self.total_mass_flow_rate = Function( + 0, "Time (s)", "Mass Depletion Rate (kg/s)" + ) + self.center_of_mass = Function(0, "Time (s)", "Center of Mass (kg)") + + # Inertia properties + self.I_11 = Function(0) + self.I_22 = Function(0) + self.I_33 = Function(0) + self.I_12 = Function(0) + self.I_13 = Function(0) + self.I_23 = Function(0) + + @funcify_method("Time (s)", "Center of Propellant Mass (kg)", "linear", "zero") + def center_of_propellant_mass(self): + return 0 + + @funcify_method("Time (s)", "Exhaust Velocity (m/s)", "linear", "zero") + def exhaust_velocity(self): + return 0 + + @property + def propellant_initial_mass(self): + return 0 + + @funcify_method("Time (s)", "Propellant I_11 (kg m²)", "linear", "zero") + def propellant_I_11(self): + return 0 + + @funcify_method("Time (s)", "Propellant I_12 (kg m²)", "linear", "zero") + def propellant_I_12(self): + return 0 + + @funcify_method("Time (s)", "Propellant I_13 (kg m²)", "linear", "zero") + def propellant_I_13(self): + return 0 + + @funcify_method("Time (s)", "Propellant I_22 (kg m²)", "linear", "zero") + def propellant_I_22(self): + return 0 + + @funcify_method("Time (s)", "Propellant I_23 (kg m²)", "linear", "zero") + def propellant_I_23(self): + return 0 + + @funcify_method("Time (s)", "Propellant I_33 (kg m²)", "linear", "zero") + def propellant_I_33(self): + return 0 + + @property + def structural_mass_ratio(self): + return 0 diff --git a/rocketpy/motors/motor.py b/rocketpy/motors/motor.py index 77c3a8633..cad0a60f4 100644 --- a/rocketpy/motors/motor.py +++ b/rocketpy/motors/motor.py @@ -1163,6 +1163,7 @@ def all_info(self): self.plots.all() +# TODO: move this class to a separate file, needs a breaking change warning class GenericMotor(Motor): """Class that represents a simple motor defined mainly by its thrust curve. There is no distinction between the propellant types (e.g. Solid, Liquid). @@ -1601,56 +1602,3 @@ def from_dict(cls, data): nozzle_position=data["nozzle_position"], interpolation_method=data["interpolate"], ) - - -class EmptyMotor: - """Class that represents an empty motor with no mass and no thrust.""" - - # TODO: This is a temporary solution. It should be replaced by a class that - # inherits from the abstract Motor class. Currently cannot be done easily. - # pylint: disable=too-many-statements - def __init__(self): - """Initializes an empty motor with no mass and no thrust. - - Notes - ----- - This class is a temporary solution to the problem of having a motor - with no mass and no thrust. It should be replaced by a class that - inherits from the abstract Motor class. Currently cannot be done easily. - """ - self._csys = 1 - self.dry_mass = 0 - self.nozzle_radius = 0 - self.thrust = Function(0, "Time (s)", "Thrust (N)") - self.propellant_mass = Function(0, "Time (s)", "Propellant Mass (kg)") - self.propellant_initial_mass = 0 - self.total_mass = Function(0, "Time (s)", "Total Mass (kg)") - self.total_mass_flow_rate = Function( - 0, "Time (s)", "Mass Depletion Rate (kg/s)" - ) - self.burn_out_time = 1 - self.nozzle_position = 0 - self.nozzle_radius = 0 - self.center_of_dry_mass_position = 0 - self.center_of_propellant_mass = Function( - 0, "Time (s)", "Center of Propellant Mass (kg)" - ) - self.center_of_mass = Function(0, "Time (s)", "Center of Mass (kg)") - self.dry_I_11 = 0 - self.dry_I_22 = 0 - self.dry_I_33 = 0 - self.dry_I_12 = 0 - self.dry_I_13 = 0 - self.dry_I_23 = 0 - self.propellant_I_11 = Function(0, "Time (s)", "Propellant I_11 (kg m²)") - self.propellant_I_22 = Function(0, "Time (s)", "Propellant I_22 (kg m²)") - self.propellant_I_33 = Function(0, "Time (s)", "Propellant I_33 (kg m²)") - self.propellant_I_12 = Function(0, "Time (s)", "Propellant I_12 (kg m²)") - self.propellant_I_13 = Function(0, "Time (s)", "Propellant I_13 (kg m²)") - self.propellant_I_23 = Function(0, "Time (s)", "Propellant I_23 (kg m²)") - self.I_11 = Function(0) - self.I_22 = Function(0) - self.I_33 = Function(0) - self.I_12 = Function(0) - self.I_13 = Function(0) - self.I_23 = Function(0) diff --git a/rocketpy/rocket/rocket.py b/rocketpy/rocket/rocket.py index ef69f7641..609e1b76c 100644 --- a/rocketpy/rocket/rocket.py +++ b/rocketpy/rocket/rocket.py @@ -6,7 +6,7 @@ from rocketpy.control.controller import _Controller from rocketpy.mathutils.function import Function from rocketpy.mathutils.vector_matrix import Matrix, Vector -from rocketpy.motors.motor import EmptyMotor +from rocketpy.motors.empty_motor import EmptyMotor from rocketpy.plots.rocket_plots import _RocketPlots from rocketpy.prints.rocket_prints import _RocketPrints from rocketpy.rocket.aero_surface import ( diff --git a/rocketpy/stochastic/stochastic_rocket.py b/rocketpy/stochastic/stochastic_rocket.py index 1f74a46a9..5f29c7f6f 100644 --- a/rocketpy/stochastic/stochastic_rocket.py +++ b/rocketpy/stochastic/stochastic_rocket.py @@ -4,7 +4,8 @@ from random import choice from rocketpy.mathutils.vector_matrix import Vector -from rocketpy.motors.motor import EmptyMotor, GenericMotor, Motor +from rocketpy.motors.empty_motor import EmptyMotor +from rocketpy.motors.motor import GenericMotor, Motor from rocketpy.motors.solid_motor import SolidMotor from rocketpy.rocket.aero_surface import ( EllipticalFins, diff --git a/tests/conftest.py b/tests/conftest.py index 31f53484a..370721cf8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,7 @@ "tests.fixtures.motor.liquid_fixtures", "tests.fixtures.motor.hybrid_fixtures", "tests.fixtures.motor.solid_motor_fixtures", + "tests.fixtures.motor.empty_motor_fixtures", "tests.fixtures.motor.tanks_fixtures", "tests.fixtures.motor.tank_geometry_fixtures", "tests.fixtures.motor.generic_motor_fixtures", diff --git a/tests/fixtures/motor/empty_motor_fixtures.py b/tests/fixtures/motor/empty_motor_fixtures.py new file mode 100644 index 000000000..4b476454e --- /dev/null +++ b/tests/fixtures/motor/empty_motor_fixtures.py @@ -0,0 +1,14 @@ +import pytest + +from rocketpy.motors.empty_motor import EmptyMotor + + +@pytest.fixture +def empty_motor(): + """An example of an empty motor with zero thrust and mass. + + Returns + ------- + rocketpy.EmptyMotor + """ + return EmptyMotor() diff --git a/tests/fixtures/motor/solid_motor_fixtures.py b/tests/fixtures/motor/solid_motor_fixtures.py index d1a9d0825..5e6e164a4 100644 --- a/tests/fixtures/motor/solid_motor_fixtures.py +++ b/tests/fixtures/motor/solid_motor_fixtures.py @@ -122,7 +122,7 @@ def dimensionless_cesaroni_m1670(kg, m): # old name: dimensionless_motor @pytest.fixture def dummy_empty_motor(): # Create a motor with ZERO thrust and ZERO mass to keep the rocket's speed constant - # TODO: why don t we use these same values to create EmptyMotor class? + # TODO: Maybe we should simple use the new `EmptyMotor` class? return SolidMotor( thrust_source=1e-300, burn_time=1e-10, diff --git a/tests/integration/test_empty_motor.py b/tests/integration/test_empty_motor.py new file mode 100644 index 000000000..9de8a82f9 --- /dev/null +++ b/tests/integration/test_empty_motor.py @@ -0,0 +1,16 @@ +from unittest.mock import patch + + +@patch("matplotlib.pyplot.show") +def test_empty_motor_info(mock_show, empty_motor): # pylint: disable=unused-argument + """Tests the LiquidMotor.all_info() method. + + Parameters + ---------- + mock_show : mock + Mock of the matplotlib.pyplot.show function. + empty_motor : rocketpy.EmptyMotor + The EmptyMotor object to be used in the tests. + """ + assert empty_motor.info() is None + assert empty_motor.all_info() is None diff --git a/tests/unit/test_rocket.py b/tests/unit/test_rocket.py index c0f6092f1..47ea61eec 100644 --- a/tests/unit/test_rocket.py +++ b/tests/unit/test_rocket.py @@ -5,7 +5,8 @@ from rocketpy import Function, NoseCone, Rocket, SolidMotor from rocketpy.mathutils.vector_matrix import Vector -from rocketpy.motors.motor import EmptyMotor, Motor +from rocketpy.motors.empty_motor import EmptyMotor +from rocketpy.motors.motor import Motor @patch("matplotlib.pyplot.show")