RingClusterMotor Class#

class rocketpy.RingClusterMotor[source]#

A class representing a cluster of N identical motors arranged symmetrically.

This class models a ring (annular) cluster configuration where a specific number of identical motors (N >= 2) are arranged symmetrically along a circular perimeter of a given radius. Note that this model assumes no central motor is present along the rocket’s longitudinal axis. The total inertia tensors (Ixx and Iyy) are computed by explicitly summing the contribution of each individual motor based on its angular position, ensuring mathematical accuracy for all configurations, including the asymmetric transverse inertia case of N=2.

Variables:
  • motor (SolidMotor) – The single motor instance used in the cluster.

  • number (int) – The number of motors in the cluster.

  • radius (float) – The radial distance from the rocket’s central axis to the center of each motor.

__init__(motor, number, radius)[source]#

Initialize the ClusterMotor.

Parameters:
  • motor (SolidMotor) – The base motor to be clustered.

  • number (int) – Number of motors. Must be >= 2.

  • radius (float) – Distance from center of rocket to center of motor (m).

_evaluate_propellant_inertia()[source]#

Calculates the dynamic inertia of the propellant using Steiner’s theorem.

I_22#

Assembled (dry + propellant) transverse inertia about the e_2 axis.

Overrides Motor.I_22(), which returns I_11 directly on the assumption that the motor is axisymmetric. That assumption does not hold for every ring cluster, so I_22 is computed here from the separately-evaluated _22 components (see _evaluate_propellant_inertia() and _calculate_dry_inertia()).

When I_22 equals I_11#

The relevant property is not continuous axisymmetry (which a discrete cluster of number motors never has for finite number) but transverse isotropy of the inertia tensor: I_11 == I_22 and I_12 == 0, i.e. every transverse axis is a principal axis with the same moment. A rigid body has this whenever it possesses a discrete rotational-symmetry axis of order n >= 3 – geometric axisymmetry is sufficient but not necessary.

For a ring cluster the motors sit at angles theta_k = 2*pi*k/number, k = 0 .. number-1, all at radius radius. The transverse anisotropy is driven by

I_22 - I_11 proportional to sum_k (x_k**2 - y_k**2)

= radius**2 * sum_k cos(2*theta_k) = radius**2 * Re( sum_k exp(i * 4*pi*k / number) ).

That geometric series vanishes unless exp(i*4*pi/number) == 1, i.e. unless number divides 2. Hence:

  • number == 2 – the m = 2 angular term does not cancel (sum cos(2*theta_k) == 2); the cluster is transversely anisotropic and I_22 != I_11. This is the case this override exists for.

  • number >= 3 – the term cancels exactly for every such value (odd, even, prime alike); I_22 == I_11 analytically, and this method returns the same value as I_11() up to floating-point round-off.

Note that parity or primality of number is irrelevant: three or more equally-spaced motors already annihilate the m = 2 harmonic, so e.g. number == 3 and number == 5 are both transversely isotropic. The sole non-trivial anisotropic configuration (given the number >= 2 constraint enforced in __init__) is number == 2.

The implementation nonetheless sums every motor’s contribution explicitly rather than special-casing number == 2, so the result is exact for all configurations.

_setup_grain_properties()[source]#

Copies the grain properties from the base motor.

property propellant_mass#

Total propellant mass as a Function of time.

Returns:

Total propellant mass as a function of time.

Return type:

Function

property propellant_initial_mass#

Propellant initial mass in kg, including solid, liquid and gas phases

Returns:

Propellant initial mass in kg.

Return type:

float

property center_of_propellant_mass#

Position of the propellant center of mass as a function of time. The position is specified as a scalar, relative to the origin of the motor’s coordinate system.

Returns:

Position of the propellant center of mass as a function of time.

Return type:

Function

property propellant_I_11#

Inertia tensor 11 component of the propellant, the inertia is relative to the e_1 axis, centered at the instantaneous propellant center of mass.

Returns:

Propellant inertia tensor 11 component at time t.

Return type:

Function

Notes

The e_1 direction is assumed to be the direction perpendicular to the motor body axis.

property propellant_I_22#

Inertia tensor 22 component of the propellant, the inertia is relative to the e_2 axis, centered at the instantaneous propellant center of mass.

Returns:

Propellant inertia tensor 22 component at time t.

Return type:

Function

Notes

The e_2 direction is assumed to be the direction perpendicular to the motor body axis, and perpendicular to e_1.

property propellant_I_33#

Inertia tensor 33 component of the propellant, the inertia is relative to the e_3 axis, centered at the instantaneous propellant center of mass.

Returns:

Propellant inertia tensor 33 component at time t.

Return type:

Function

Notes

The e_3 direction is assumed to be the axial direction of the rocket motor.

property propellant_I_12#

Inertia tensor 12 component of the propellant, the product of inertia is relative to axes e_1 and e_2, centered at the instantaneous propellant center of mass.

Returns:

Propellant inertia tensor 12 component at time t.

Return type:

Function

Notes

The e_1 direction is assumed to be the direction perpendicular to the motor body axis. The e_2 direction is assumed to be the direction perpendicular to the motor body axis, and perpendicular to e_1. RocketPy follows the definition of the inertia tensor as in [1], which includes the minus sign for all products of inertia.

property propellant_I_13#

Inertia tensor 13 component of the propellant, the product of inertia is relative to axes e_1 and e_3, centered at the instantaneous propellant center of mass.

Returns:

Propellant inertia tensor 13 component at time t.

Return type:

Function

Notes

The e_1 direction is assumed to be the direction perpendicular to the motor body axis. The e_3 direction is assumed to be the axial direction of the rocket motor. RocketPy follows the definition of the inertia tensor as in [1], which includes the minus sign for all products of inertia.

property propellant_I_23#

Inertia tensor 23 component of the propellant, the product of inertia is relative to axes e_2 and e_3, centered at the instantaneous propellant center of mass.

Returns:

Propellant inertia tensor 23 component at time t.

Return type:

Function

Notes

The e_2 direction is assumed to be the direction perpendicular to the motor body axis, and perpendicular to e_1. The e_3 direction is assumed to be the axial direction of the rocket motor. RocketPy follows the definition of the inertia tensor as in [1], which includes the minus sign for all products of inertia.

property exhaust_velocity#

Effective exhaust velocity of the motor gases.

Returns:

self.exhaust_velocity – Gas exhaust velocity of the motor.

Return type:

Function

Notes

This method is implemented in the following manner by the child Motor classes:

  • The SolidMotor assumes a constant exhaust velocity and computes it as the ratio of the total impulse and the propellant mass;

  • The HybridMotor assumes a constant exhaust velocity and computes it as the ratio of the total impulse and the propellant mass;

  • The LiquidMotor class favors the more accurate data from the Tanks’s mass flow rates. Therefore the exhaust velocity is generally variable, being the ratio of the motor thrust by the mass flow rate.

This corresponds to the actual exhaust velocity only when the nozzle exit pressure equals the atmospheric pressure.

info(*args, **kwargs)[source]#

Prints out a summary of the data and graphs available about the Motor.

Parameters:

filename (str | None, optional) – The path the plot should be saved to. By default None, in which case the plot will be shown instead of saved. Supported file endings are: eps, jpg, jpeg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff and webp (these are the formats supported by matplotlib).

Return type:

None

draw_cluster_layout(rocket_radius=None, show=True)[source]#

Draw the geometric layout of the clustered motors.

_draw_engines(ax)[source]#

Draws the individual engines of the cluster.