From f048c565ae2e019116718aa6e981c62d2d3ed811 Mon Sep 17 00:00:00 2001 From: caioessouza Date: Thu, 24 Apr 2025 19:06:12 -0300 Subject: [PATCH 1/6] Functions associated to the regression updated #801 only_radial_burn optional parameter added and used in the functions related to the grain regression as a conditon to change the applied equations. Still need to update the comment section, the CHANGELOG and maybe the dict related functions, but not sure about the last one yet. --- rocketpy/motors/solid_motor.py | 137 +++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 41 deletions(-) diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index 37d89130e..357bd7434 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -204,6 +204,7 @@ def __init__( reshape_thrust_curve=False, interpolation_method="linear", coordinate_system_orientation="nozzle_to_combustion_chamber", + only_radial_burn=False, ): """Initialize Motor class, process thrust curve and geometrical parameters and store results. @@ -315,6 +316,7 @@ class Function. Thrust units are Newtons. reshape_thrust_curve=reshape_thrust_curve, interpolation_method=interpolation_method, coordinate_system_orientation=coordinate_system_orientation, + only_radial_burn = only_radial_burn, ) # Nozzle parameters self.throat_radius = throat_radius @@ -339,6 +341,8 @@ class Function. Thrust units are Newtons. self.evaluate_geometry() + # Burn surface definition + self.only_radial_burn = only_radial_burn # Initialize plots and prints object self.prints = _SolidMotorPrints(self) self.plots = _SolidMotorPlots(self) @@ -479,15 +483,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 + ) ) - ) + 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 @@ -500,33 +514,64 @@ 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 = factor * grain_inner_radius + height_derivative_wrt_inner_radius = 0 + height_derivative_wrt_height = 0 + + 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] return end_function @@ -576,16 +621,26 @@ 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)") From 4f32f88d2f5c747b0b85097a95e400903b7662c5 Mon Sep 17 00:00:00 2001 From: caioessouza Date: Wed, 30 Apr 2025 19:42:03 -0300 Subject: [PATCH 2/6] super() corrected and dict functions updated #801 The new parameter of the SolidMotor class was removed from super, since it's not on the Motor class. The dict functions were updated to take this new parameter into acount. Also the comments about the SolidMotor class parameters were updated. Still need to do some tests running the code to be sure everything is ok, then I can open the PR. --- rocketpy/motors/solid_motor.py | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index 357bd7434..66f69938f 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -300,6 +300,11 @@ class Function. Thrust units are Newtons. positions specified. Options are "nozzle_to_combustion_chamber" and "combustion_chamber_to_nozzle". Default is "nozzle_to_combustion_chamber". + only_radial_burn : boolean, optional + If True, inhibits the grain from burning axially, only computing + radial burn. Otherwise, if False, allows the grain to also burn + axially. May be useful for axially inhibited grains or hybrid motors. + Default is False. Returns ------- @@ -316,7 +321,6 @@ class Function. Thrust units are Newtons. reshape_thrust_curve=reshape_thrust_curve, interpolation_method=interpolation_method, coordinate_system_orientation=coordinate_system_orientation, - only_radial_burn = only_radial_burn, ) # Nozzle parameters self.throat_radius = throat_radius @@ -484,13 +488,7 @@ def geometry_dot(t, y): # Compute state vector derivative grain_inner_radius, grain_height = y if self.only_radial_burn: - burn_area = ( - 2 - * np.pi - * ( - grain_inner_radius * grain_height - ) - ) + burn_area = 2 * np.pi * (grain_inner_radius * grain_height) else: burn_area = ( 2 @@ -516,12 +514,7 @@ def geometry_jacobian(t, y): grain_inner_radius, grain_height = y if self.only_radial_burn: factor = volume_diff / ( - 2 - * np.pi - * ( - grain_inner_radius * grain_height - ) - ** 2 + 2 * np.pi * (grain_inner_radius * grain_height) ** 2 ) inner_radius_derivative_wrt_inner_radius = factor * ( @@ -537,8 +530,6 @@ def geometry_jacobian(t, y): inner_radius_derivative_wrt_height, ], [height_derivative_wrt_inner_radius, height_derivative_wrt_height], - - ] else: @@ -568,10 +559,8 @@ def geometry_jacobian(t, y): 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] return end_function @@ -625,9 +614,7 @@ def burn_area(self): burn_area = ( 2 * np.pi - * ( - self.grain_inner_radius * self.grain_height - ) + * (self.grain_inner_radius * self.grain_height) * self.grain_number ) else: @@ -812,6 +799,7 @@ def to_dict(self, include_outputs=False): "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, } ) @@ -855,4 +843,5 @@ def from_dict(cls, data): throat_radius=data["throat_radius"], interpolation_method=data["interpolate"], coordinate_system_orientation=data["coordinate_system_orientation"], + only_radial_burn=data.get("only_radial_burn", False), ) From 550e149fac7a3703f57b43810d9b6417b99e55d1 Mon Sep 17 00:00:00 2001 From: caioessouza Date: Sat, 3 May 2025 08:48:49 -0300 Subject: [PATCH 3/6] Last update #801 Corrected some minor code erros, like calling evaluate geometry before defining self.only_radial_burn. Also had to change the grain_height_derivative to zero in the case of only radial burn, it was leading to some physical incoherences, because the grain was still burning axially. The last tests to evaluate the physical behaviour went pretty well, so I'll open the PR. --- rocketpy/motors/solid_motor.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index 66f69938f..dba121dda 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -302,7 +302,7 @@ class Function. Thrust units are Newtons. "nozzle_to_combustion_chamber". only_radial_burn : boolean, optional If True, inhibits the grain from burning axially, only computing - radial burn. Otherwise, if False, allows the grain to also burn + radial burn. Otherwise, if False, allows the grain to also burn axially. May be useful for axially inhibited grains or hybrid motors. Default is False. @@ -343,10 +343,11 @@ class Function. Thrust units are Newtons. ) self.grain_initial_mass = self.grain_density * self.grain_initial_volume - self.evaluate_geometry() - # Burn surface definition self.only_radial_burn = only_radial_burn + + self.evaluate_geometry() + # Initialize plots and prints object self.prints = _SolidMotorPrints(self) self.plots = _SolidMotorPlots(self) @@ -489,6 +490,10 @@ def geometry_dot(t, y): grain_inner_radius, grain_height = y 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 + else: burn_area = ( 2 @@ -500,8 +505,8 @@ def geometry_dot(t, y): ) ) - 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] @@ -520,7 +525,7 @@ def geometry_jacobian(t, y): inner_radius_derivative_wrt_inner_radius = factor * ( grain_height - 2 * grain_inner_radius ) - inner_radius_derivative_wrt_height = factor * grain_inner_radius + inner_radius_derivative_wrt_height = 0 height_derivative_wrt_inner_radius = 0 height_derivative_wrt_height = 0 From 7a4267ae85391f6a9e15f34aa48d54a72ca4c4a6 Mon Sep 17 00:00:00 2001 From: caioessouza Date: Fri, 9 May 2025 20:46:46 -0300 Subject: [PATCH 4/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a2503d23..31ae251b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Attention: The newest changes should be on top --> ### Added +- ENH: Enable only radial burning [#815](https://github.com/RocketPy-Team/RocketPy/pull/815) - ENH: Parallel mode for monte-carlo simulations 2 [#768](https://github.com/RocketPy-Team/RocketPy/pull/768) - DOC: ASTRA Flight Example [#770](https://github.com/RocketPy-Team/RocketPy/pull/770) - ENH: Add Eccentricity to Stochastic Simulations [#792](https://github.com/RocketPy-Team/RocketPy/pull/792) From 32871380e76a6dc1420865f3400db146cdc80e8f Mon Sep 17 00:00:00 2001 From: caioessouza Date: Tue, 20 May 2025 10:54:14 -0300 Subject: [PATCH 5/6] Only radial burning enabled on hybrid class #801 The "only_radial_burning" parameter was added and set as default on the hybrid class. Also, the description of the new parameter was updated and 2 coments about derivatives set to zero were added. --- rocketpy/motors/hybrid_motor.py | 2 ++ rocketpy/motors/solid_motor.py | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/rocketpy/motors/hybrid_motor.py b/rocketpy/motors/hybrid_motor.py index ea01e686f..2ae50d073 100644 --- a/rocketpy/motors/hybrid_motor.py +++ b/rocketpy/motors/hybrid_motor.py @@ -203,6 +203,7 @@ def __init__( # pylint: disable=too-many-arguments reshape_thrust_curve=False, interpolation_method="linear", coordinate_system_orientation="nozzle_to_combustion_chamber", + only_radial_burn=True, ): """Initialize Motor class, process thrust curve and geometrical parameters and store results. @@ -346,6 +347,7 @@ class Function. Thrust units are Newtons. reshape_thrust_curve, interpolation_method, coordinate_system_orientation, + only_radial_burn, ) self.positioned_tanks = self.liquid.positioned_tanks diff --git a/rocketpy/motors/solid_motor.py b/rocketpy/motors/solid_motor.py index dba121dda..941b10019 100644 --- a/rocketpy/motors/solid_motor.py +++ b/rocketpy/motors/solid_motor.py @@ -302,7 +302,7 @@ class Function. Thrust units are Newtons. "nozzle_to_combustion_chamber". only_radial_burn : boolean, optional If True, inhibits the grain from burning axially, only computing - radial burn. Otherwise, if False, allows the grain to also burn + radial burn. If False, allows the grain to also burn axially. May be useful for axially inhibited grains or hybrid motors. Default is False. @@ -492,7 +492,7 @@ def geometry_dot(t, y): burn_area = 2 * np.pi * (grain_inner_radius * grain_height) grain_inner_radius_derivative = -volume_diff / burn_area - grain_height_derivative = 0 + grain_height_derivative = 0 # Set to zero to disable axial burning else: burn_area = ( @@ -528,6 +528,7 @@ def geometry_jacobian(t, y): 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 [ [ From d97ba24726feee84fcd5a4dd7ecb7e870f225029 Mon Sep 17 00:00:00 2001 From: caioessouza Date: Fri, 30 May 2025 17:14:36 -0300 Subject: [PATCH 6/6] only_radial_burn on hybrid corrected only_radial_burn argument order corrected --- rocketpy/motors/hybrid_motor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rocketpy/motors/hybrid_motor.py b/rocketpy/motors/hybrid_motor.py index 9a1eb6636..12b270645 100644 --- a/rocketpy/motors/hybrid_motor.py +++ b/rocketpy/motors/hybrid_motor.py @@ -215,8 +215,8 @@ def __init__( # pylint: disable=too-many-arguments reshape_thrust_curve=False, interpolation_method="linear", coordinate_system_orientation="nozzle_to_combustion_chamber", - only_radial_burn=True, reference_pressure=None, + only_radial_burn=True, ): """Initialize Motor class, process thrust curve and geometrical parameters and store results. @@ -364,8 +364,8 @@ class Function. Thrust units are Newtons. reshape_thrust_curve, interpolation_method, coordinate_system_orientation, - only_radial_burn, reference_pressure, + only_radial_burn, ) self.positioned_tanks = self.liquid.positioned_tanks