Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f048c56
Functions associated to the regression updated #801
caioessouza Apr 24, 2025
4f32f88
super() corrected and dict functions updated #801
caioessouza Apr 30, 2025
550e149
Last update #801
caioessouza May 3, 2025
7a4267a
Update CHANGELOG.md
caioessouza May 9, 2025
95970b9
Merge branch 'develop' into enh/enable-only-radial-burning
MateusStano May 16, 2025
3287138
Only radial burning enabled on hybrid class #801
caioessouza May 20, 2025
02de507
Merge branch 'enh/enable-only-radial-burning' of https://github.com/c…
caioessouza May 20, 2025
d97ba24
only_radial_burn on hybrid corrected
caioessouza May 30, 2025
0cb0eb5
Tests created
caioessouza Aug 13, 2025
8de2ab4
Corrections made based in the review
caioessouza Aug 14, 2025
e681877
Merge branch 'develop' into enh/enable-only-radial-burning
caioessouza Aug 14, 2025
4e4df54
Tests approved
caioessouza Oct 2, 2025
c941070
Merge branch 'enh/enable-only-radial-burning' of https://github.com/c…
caioessouza Oct 2, 2025
2b3a15c
Merge branch 'develop' into enh/enable-only-radial-burning
caioessouza Oct 2, 2025
79e2a1c
Unit tests
caioessouza Oct 2, 2025
3ecf1d7
Merge branch 'enh/enable-only-radial-burning' of https://github.com/c…
caioessouza Oct 2, 2025
65dfa23
Merge branch 'develop' into enh/enable-only-radial-burning
caioessouza Oct 2, 2025
79c066c
Integration mock_show correction
caioessouza Oct 2, 2025
32f7711
Merge branch 'enh/enable-only-radial-burning' of https://github.com/c…
caioessouza Oct 2, 2025
f92cb64
mock_show returned to unit tests
caioessouza Oct 2, 2025
d9d99dd
Integration problem solved
caioessouza Oct 2, 2025
cb3c3a2
Ruff run again
caioessouza Oct 3, 2025
8ebbc90
Sugestions Update
caioessouza Oct 3, 2025
292ab84
Ruff format run
caioessouza Oct 3, 2025
b99afb1
Removed @property
caioessouza Oct 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
Attention: The newest changes should be on top -->

### Added
- ENH: Enable only radial burning [#815](https://github.com/RocketPy-Team/RocketPy/pull/815)
- ENH: Tank Fluids with Variable Density from Temperature and Pressure [#852](https://github.com/RocketPy-Team/RocketPy/pull/852)
- ENH: Controller (AirBrakes) and Sensors Encoding [#849](https://github.com/RocketPy-Team/RocketPy/pull/849)
- EHN: Addition of ensemble variable to ECMWF dictionaries [#842](https://github.com/RocketPy-Team/RocketPy/pull/842)
Expand Down Expand Up @@ -476,4 +477,4 @@ You can install this version by running `pip install rocketpy==1.0.1`
### Fixed

- BUG: Remove NoseCone Warning [#428](https://github.com/RocketPy-Team/RocketPy/pull/428)
- BUG: motor coordinates [#423](https://github.com/RocketPy-Team/RocketPy/pull/423)
- BUG: motor coordinates [#423](https://github.com/RocketPy-Team/RocketPy/pull/423)
11 changes: 11 additions & 0 deletions rocketpy/motors/hybrid_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,12 @@ class HybridMotor(Motor):
HybridMotor.reference_pressure : int, float
Atmospheric pressure in Pa at which the thrust data was recorded.
It will allow to obtain the net thrust in the Flight class.
SolidMotor.only_radial_burn : bool
If True, grain regression is restricted to radial burn only (inner radius growth).
Grain length remains constant throughout the burn. Default is False.
"""

# pylint: disable=too-many-arguments
def __init__( # pylint: disable=too-many-arguments
self,
thrust_source,
Expand All @@ -216,6 +220,7 @@ def __init__( # pylint: disable=too-many-arguments
interpolation_method="linear",
coordinate_system_orientation="nozzle_to_combustion_chamber",
reference_pressure=None,
only_radial_burn=True,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There can be made some discussion here on the severity of it, but this is likely a breaking change: the default of this attribute should be False, otherwise all the current code with hybrid motors would have its behavior changed. Do you agree @Gui-FernandesBR ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this change would break anything, but I think it can change the propellant mass evolution with time. Anyway, this behaviour is more similar to reality, so in my conception even if it changes, it's not necessarily a bad thing. Do you agree @Gui-FernandesBR @MateusStano ? If you think it's a problem, I can change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it changes results, and I understand it changes for the better.

@phmbressan don't you think we could proceed with this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This parameter needs to be documented in the class and __init__ docstrings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check, please review again to make sure everything is ok

):
"""Initialize Motor class, process thrust curve and geometrical
parameters and store results.
Expand Down Expand Up @@ -313,6 +318,11 @@ class Function. Thrust units are Newtons.
"nozzle_to_combustion_chamber".
reference_pressure : int, float, optional
Atmospheric pressure in Pa at which the thrust data was recorded.
only_radial_burn : boolean, optional
If True, inhibits the grain from burning axially, only computing
radial burn. If False, allows the grain to also burn
axially. May be useful for axially inhibited grains or hybrid motors.
Default is False.

Returns
-------
Expand Down Expand Up @@ -364,6 +374,7 @@ class Function. Thrust units are Newtons.
interpolation_method,
coordinate_system_orientation,
reference_pressure,
only_radial_burn,
)

self.positioned_tanks = self.liquid.positioned_tanks
Expand Down
143 changes: 100 additions & 43 deletions rocketpy/motors/solid_motor.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ class SolidMotor(Motor):
SolidMotor.reference_pressure : int, float
Atmospheric pressure in Pa at which the thrust data was recorded.
It will allow to obtain the net thrust in the Flight class.
SolidMotor.only_radial_burn : bool
If True, grain regression is restricted to radial burn only (inner radius growth).
Grain length remains constant throughout the burn. Default is False.
"""

# pylint: disable=too-many-arguments
Expand All @@ -217,6 +220,7 @@ def __init__(
interpolation_method="linear",
coordinate_system_orientation="nozzle_to_combustion_chamber",
reference_pressure=None,
only_radial_burn=False,
):
"""Initialize Motor class, process thrust curve and geometrical
parameters and store results.
Expand Down Expand Up @@ -314,6 +318,11 @@ class Function. Thrust units are Newtons.
"nozzle_to_combustion_chamber".
reference_pressure : int, float, optional
Atmospheric pressure in Pa at which the thrust data was recorded.
only_radial_burn : boolean, optional
If True, inhibits the grain from burning axially, only computing
radial burn. If False, allows the grain to also burn
axially. May be useful for axially inhibited grains or hybrid motors.
Default is False.

Returns
-------
Expand Down Expand Up @@ -353,6 +362,9 @@ class Function. Thrust units are Newtons.
)
self.grain_initial_mass = self.grain_density * self.grain_initial_volume

# Burn surface definition
self.only_radial_burn = only_radial_burn

self.evaluate_geometry()

# Initialize plots and prints object
Expand Down Expand Up @@ -405,6 +417,10 @@ def exhaust_velocity(self):
self.total_impulse / self.propellant_initial_mass
).set_discrete_based_on_model(self.thrust)

# @property
# def only_radial_burn(self):
# return self._only_radial_burn

@property
def propellant_initial_mass(self):
"""Returns the initial propellant mass.
Expand Down Expand Up @@ -500,17 +516,25 @@ def geometry_dot(t, y):

# Compute state vector derivative
grain_inner_radius, grain_height = y
burn_area = (
2
* np.pi
* (
grain_outer_radius**2
- grain_inner_radius**2
+ grain_inner_radius * grain_height
if self.only_radial_burn:
burn_area = 2 * np.pi * (grain_inner_radius * grain_height)

grain_inner_radius_derivative = -volume_diff / burn_area
grain_height_derivative = 0 # Set to zero to disable axial burning

else:
burn_area = (
2
* np.pi
* (
grain_outer_radius**2
- grain_inner_radius**2
+ grain_inner_radius * grain_height
)
)
)
grain_inner_radius_derivative = -volume_diff / burn_area
grain_height_derivative = -2 * grain_inner_radius_derivative

grain_inner_radius_derivative = -volume_diff / burn_area
grain_height_derivative = -2 * grain_inner_radius_derivative

return [grain_inner_radius_derivative, grain_height_derivative]

Expand All @@ -521,32 +545,55 @@ def geometry_jacobian(t, y):

# Compute jacobian
grain_inner_radius, grain_height = y
factor = volume_diff / (
2
* np.pi
* (
grain_outer_radius**2
- grain_inner_radius**2
+ grain_inner_radius * grain_height
if self.only_radial_burn:
factor = volume_diff / (
2 * np.pi * (grain_inner_radius * grain_height) ** 2
)
** 2
)
inner_radius_derivative_wrt_inner_radius = factor * (
grain_height - 2 * grain_inner_radius
)
inner_radius_derivative_wrt_height = factor * grain_inner_radius
height_derivative_wrt_inner_radius = (
-2 * inner_radius_derivative_wrt_inner_radius
)
height_derivative_wrt_height = -2 * inner_radius_derivative_wrt_height

return [
[
inner_radius_derivative_wrt_inner_radius,
inner_radius_derivative_wrt_height,
],
[height_derivative_wrt_inner_radius, height_derivative_wrt_height],
]
inner_radius_derivative_wrt_inner_radius = factor * (
grain_height - 2 * grain_inner_radius
)
inner_radius_derivative_wrt_height = 0
height_derivative_wrt_inner_radius = 0
height_derivative_wrt_height = 0
# Height is a constant, so all the derivatives with respect to it are set to zero

return [
[
inner_radius_derivative_wrt_inner_radius,
inner_radius_derivative_wrt_height,
],
[height_derivative_wrt_inner_radius, height_derivative_wrt_height],
]

else:
factor = volume_diff / (
2
* np.pi
* (
grain_outer_radius**2
- grain_inner_radius**2
+ grain_inner_radius * grain_height
)
** 2
)

inner_radius_derivative_wrt_inner_radius = factor * (
grain_height - 2 * grain_inner_radius
)
inner_radius_derivative_wrt_height = factor * grain_inner_radius
height_derivative_wrt_inner_radius = (
-2 * inner_radius_derivative_wrt_inner_radius
)
height_derivative_wrt_height = -2 * inner_radius_derivative_wrt_height

return [
[
inner_radius_derivative_wrt_inner_radius,
inner_radius_derivative_wrt_height,
],
[height_derivative_wrt_inner_radius, height_derivative_wrt_height],
]

def terminate_burn(t, y): # pylint: disable=unused-argument
end_function = (self.grain_outer_radius - y[0]) * y[1]
Expand Down Expand Up @@ -597,16 +644,24 @@ def burn_area(self):
burn_area : Function
Function representing the burn area progression with the time.
"""
burn_area = (
2
* np.pi
* (
self.grain_outer_radius**2
- self.grain_inner_radius**2
+ self.grain_inner_radius * self.grain_height
if self.only_radial_burn:
burn_area = (
2
* np.pi
* (self.grain_inner_radius * self.grain_height)
* self.grain_number
)
else:
burn_area = (
2
* np.pi
* (
self.grain_outer_radius**2
- self.grain_inner_radius**2
+ self.grain_inner_radius * self.grain_height
)
* self.grain_number
)
* self.grain_number
)
return burn_area

@funcify_method("Time (s)", "burn rate (m/s)")
Expand Down Expand Up @@ -778,6 +833,7 @@ def to_dict(self, **kwargs):
"grain_initial_height": self.grain_initial_height,
"grain_separation": self.grain_separation,
"grains_center_of_mass_position": self.grains_center_of_mass_position,
"only_radial_burn": self.only_radial_burn,
}
)

Expand Down Expand Up @@ -827,4 +883,5 @@ def from_dict(cls, data):
interpolation_method=data["interpolate"],
coordinate_system_orientation=data["coordinate_system_orientation"],
reference_pressure=data.get("reference_pressure"),
only_radial_burn=data.get("only_radial_burn", False),
)
4 changes: 2 additions & 2 deletions tests/fixtures/motor/hybrid_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@pytest.fixture
def hybrid_motor(spherical_oxidizer_tank):
def hybrid_motor(oxidizer_tank):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't oppose to it if needed, but any particular reason for changing the fixture name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spherical_oxidizer_tank fixture is broken. It's giving negative liquid heights. It need to be fixed in another issue.

"""An example of a hybrid motor with spherical oxidizer
tank and fuel grains.

Expand Down Expand Up @@ -35,6 +35,6 @@ def hybrid_motor(spherical_oxidizer_tank):
grains_center_of_mass_position=-0.1,
)

motor.add_tank(spherical_oxidizer_tank, position=0.3)
motor.add_tank(oxidizer_tank, position=0.3)

return motor
16 changes: 16 additions & 0 deletions tests/integration/test_solidmotor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from unittest.mock import patch


@patch("matplotlib.pyplot.show")
def test_solid_motor_info(mock_show, cesaroni_m1670): # pylint: disable=unused-argument
"""Tests the SolidMotor.all_info() method.

Parameters
----------
mock_show : mock
Mock of the matplotlib.pyplot.show function.
cesaroni_m1670 : rocketpy.SolidMotor
The SolidMotor object to be used in the tests.
"""
assert cesaroni_m1670.info() is None
assert cesaroni_m1670.all_info() is None
Loading