Skip to content

models.motors

Top-level motor/engine definitions that assemble all physical sub-components into a complete propulsion unit.

  • SolidMotor — Combines a Grain, SolidPropellant, and SolidMotorThrustChamber. Provides launch/dry mass, free chamber volume, CoG (mass-weighted across grain and hardware), and thrust coefficient with loss corrections.
  • BiliquidEngine — Combines a BiliquidPropellant, BiliquidEngineThrustChamber, and FeedSystem. Tracks CoG shift as propellant is consumed from the tanks.

Both inherit from the generic Motor[P, T] base class. A motor instance is the primary input to InternalBallisticsSimulation.

machwave.models.motors

BiliquidEngine

Bases: Motor[BiliquidPropellant, BiliquidEngineThrustChamber]

Biliquid rocket engine with a bipropellant feed system.

Source code in machwave/models/motors/biliquid.py
class BiliquidEngine(
    motor_base.Motor[
        propellants.BiliquidPropellant,
        thrust_chamber_models.BiliquidEngineThrustChamber,
    ]
):
    """Biliquid rocket engine with a bipropellant feed system."""

    def __init__(
        self,
        propellant: propellants.BiliquidPropellant,
        thrust_chamber: thrust_chamber_models.BiliquidEngineThrustChamber,
        feed_system: feed_system_base.FeedSystem,
        combustion_efficiency: float = 0.95,
        nozzle_loss_model: nozzle_losses.NozzleLossModel | None = None,
    ) -> None:
        """
        Initialize a biliquid rocket engine.

        Args:
            propellant: Biliquid propellant properties (oxidizer + fuel).
            thrust_chamber: Thrust chamber assembly (nozzle, combustion chamber,
                injector).
            feed_system: Propellant feed system (tanks, lines, pumps or
                pressurization).
            combustion_efficiency: Ratio of the actual flame temperature to the ideal
                adiabatic flame temperature (0, 1].
            nozzle_loss_model: Nozzle loss model.
        """
        super().__init__(
            propellant,
            thrust_chamber,
            combustion_efficiency,
            nozzle_loss_model=nozzle_loss_model
            or nozzle_losses.presets.constant_efficiency_loss_model(
                mixture_type=propellants.MixtureType.BILIQUID
            ),
        )
        self.feed_system = feed_system

    @property
    def initial_propellant_mass(self) -> float:
        """Return the initial propellant mass [kg]."""
        return self.feed_system.get_initial_propellant_mass()

initial_propellant_mass property

Return the initial propellant mass [kg].

__init__(propellant, thrust_chamber, feed_system, combustion_efficiency=0.95, nozzle_loss_model=None)

Initialize a biliquid rocket engine.

Parameters:

Name Type Description Default
propellant BiliquidPropellant

Biliquid propellant properties (oxidizer + fuel).

required
thrust_chamber BiliquidEngineThrustChamber

Thrust chamber assembly (nozzle, combustion chamber, injector).

required
feed_system FeedSystem

Propellant feed system (tanks, lines, pumps or pressurization).

required
combustion_efficiency float

Ratio of the actual flame temperature to the ideal adiabatic flame temperature (0, 1].

0.95
nozzle_loss_model NozzleLossModel | None

Nozzle loss model.

None
Source code in machwave/models/motors/biliquid.py
def __init__(
    self,
    propellant: propellants.BiliquidPropellant,
    thrust_chamber: thrust_chamber_models.BiliquidEngineThrustChamber,
    feed_system: feed_system_base.FeedSystem,
    combustion_efficiency: float = 0.95,
    nozzle_loss_model: nozzle_losses.NozzleLossModel | None = None,
) -> None:
    """
    Initialize a biliquid rocket engine.

    Args:
        propellant: Biliquid propellant properties (oxidizer + fuel).
        thrust_chamber: Thrust chamber assembly (nozzle, combustion chamber,
            injector).
        feed_system: Propellant feed system (tanks, lines, pumps or
            pressurization).
        combustion_efficiency: Ratio of the actual flame temperature to the ideal
            adiabatic flame temperature (0, 1].
        nozzle_loss_model: Nozzle loss model.
    """
    super().__init__(
        propellant,
        thrust_chamber,
        combustion_efficiency,
        nozzle_loss_model=nozzle_loss_model
        or nozzle_losses.presets.constant_efficiency_loss_model(
            mixture_type=propellants.MixtureType.BILIQUID
        ),
    )
    self.feed_system = feed_system

Motor

Bases: Generic[P, T], ABC

Abstract rocket motor/engine for solid, hybrid, or biliquid systems.

Source code in machwave/models/motors/base.py
class Motor(Generic[P, T], ABC):
    """Abstract rocket motor/engine for solid, hybrid, or biliquid systems."""

    def __init__(
        self,
        propellant: P,
        thrust_chamber: T,
        combustion_efficiency: float = 0.95,
        nozzle_loss_model: nozzle_losses.NozzleLossModel | None = None,
    ) -> None:
        """
        Initialize attributes common to any motor or engine.

        Args:
            propellant: Propellant used in the motor.
            thrust_chamber: Thrust chamber of the motor.
            combustion_efficiency: Ratio of the actual flame temperature to the ideal
                adiabatic flame temperature (0, 1].
            nozzle_loss_model: Nozzle thrust coefficient loss model. Motor
                subclasses supply an engine-appropriate default.

        Raises:
            ValueError: If `combustion_efficiency` is not in (0, 1], if
                `nozzle_loss_model` is missing, or if its mixture type does not
                match the propellant.
        """
        if not 0.0 < combustion_efficiency <= 1.0:
            raise ValueError(
                "combustion_efficiency must be in the range (0, 1], got "
                f"{combustion_efficiency}"
            )

        if nozzle_loss_model is None:
            raise ValueError(
                "nozzle_loss_model must be provided; motor subclasses supply a default."
            )

        if nozzle_loss_model.mixture_type != propellant.mixture_type:
            raise ValueError(
                "nozzle_loss_model mixture type "
                f"{nozzle_loss_model.mixture_type} does not match propellant "
                f"mixture type {propellant.mixture_type}."
            )

        self.propellant = propellant
        self.thrust_chamber = thrust_chamber
        self.combustion_efficiency = combustion_efficiency
        self.nozzle_loss_model = nozzle_loss_model

    @property
    @abstractmethod
    def initial_propellant_mass(self) -> float:
        """Return the initial propellant mass [kg]."""
        pass

initial_propellant_mass abstractmethod property

Return the initial propellant mass [kg].

__init__(propellant, thrust_chamber, combustion_efficiency=0.95, nozzle_loss_model=None)

Initialize attributes common to any motor or engine.

Parameters:

Name Type Description Default
propellant P

Propellant used in the motor.

required
thrust_chamber T

Thrust chamber of the motor.

required
combustion_efficiency float

Ratio of the actual flame temperature to the ideal adiabatic flame temperature (0, 1].

0.95
nozzle_loss_model NozzleLossModel | None

Nozzle thrust coefficient loss model. Motor subclasses supply an engine-appropriate default.

None

Raises:

Type Description
ValueError

If combustion_efficiency is not in (0, 1], if nozzle_loss_model is missing, or if its mixture type does not match the propellant.

Source code in machwave/models/motors/base.py
def __init__(
    self,
    propellant: P,
    thrust_chamber: T,
    combustion_efficiency: float = 0.95,
    nozzle_loss_model: nozzle_losses.NozzleLossModel | None = None,
) -> None:
    """
    Initialize attributes common to any motor or engine.

    Args:
        propellant: Propellant used in the motor.
        thrust_chamber: Thrust chamber of the motor.
        combustion_efficiency: Ratio of the actual flame temperature to the ideal
            adiabatic flame temperature (0, 1].
        nozzle_loss_model: Nozzle thrust coefficient loss model. Motor
            subclasses supply an engine-appropriate default.

    Raises:
        ValueError: If `combustion_efficiency` is not in (0, 1], if
            `nozzle_loss_model` is missing, or if its mixture type does not
            match the propellant.
    """
    if not 0.0 < combustion_efficiency <= 1.0:
        raise ValueError(
            "combustion_efficiency must be in the range (0, 1], got "
            f"{combustion_efficiency}"
        )

    if nozzle_loss_model is None:
        raise ValueError(
            "nozzle_loss_model must be provided; motor subclasses supply a default."
        )

    if nozzle_loss_model.mixture_type != propellant.mixture_type:
        raise ValueError(
            "nozzle_loss_model mixture type "
            f"{nozzle_loss_model.mixture_type} does not match propellant "
            f"mixture type {propellant.mixture_type}."
        )

    self.propellant = propellant
    self.thrust_chamber = thrust_chamber
    self.combustion_efficiency = combustion_efficiency
    self.nozzle_loss_model = nozzle_loss_model

SolidMotor

Bases: Motor[SolidPropellant, SolidMotorThrustChamber]

Solid rocket motor with a propellant grain and thrust chamber.

Source code in machwave/models/motors/solid.py
class SolidMotor(
    motor_base.Motor[
        propellants.SolidPropellant, thrust_chamber.SolidMotorThrustChamber
    ]
):
    """Solid rocket motor with a propellant grain and thrust chamber."""

    def __init__(
        self,
        grain: grain.Grain,
        propellant: propellants.SolidPropellant,
        thrust_chamber: thrust_chamber.SolidMotorThrustChamber,
        combustion_efficiency: float = 0.95,
        nozzle_loss_model: nozzle_losses.NozzleLossModel | None = None,
    ) -> None:
        """
        Initialize a solid rocket motor.

        Args:
            grain: Grain geometry configuration.
            propellant: Solid propellant properties.
            thrust_chamber: Thrust chamber model.
            combustion_efficiency: Ratio of the actual flame temperature to the ideal
                adiabatic flame temperature (0, 1].
            nozzle_loss_model: Nozzle loss model.
        """
        super().__init__(
            propellant,
            thrust_chamber,
            combustion_efficiency,
            nozzle_loss_model=nozzle_loss_model
            or nozzle_losses.presets.spp1975_solid_loss_model(),
        )

        self.grain = grain
        self.propellant: propellants.SolidPropellant = propellant

    def get_free_chamber_volume(self, propellant_volume: float) -> float:
        """
        Return the chamber volume without any propellant.

        Args:
            propellant_volume: Propellant volume [m^3].

        Returns:
            Free chamber volume [m^3].
        """
        return (
            self.thrust_chamber.combustion_chamber.internal_volume - propellant_volume
        )

    @property
    def initial_propellant_mass(self) -> float:
        """Return the initial propellant mass [kg]."""
        return self.grain.get_propellant_mass(
            web_distance=0, ideal_density=self.propellant.ideal_density
        )

initial_propellant_mass property

Return the initial propellant mass [kg].

__init__(grain, propellant, thrust_chamber, combustion_efficiency=0.95, nozzle_loss_model=None)

Initialize a solid rocket motor.

Parameters:

Name Type Description Default
grain Grain

Grain geometry configuration.

required
propellant SolidPropellant

Solid propellant properties.

required
thrust_chamber SolidMotorThrustChamber

Thrust chamber model.

required
combustion_efficiency float

Ratio of the actual flame temperature to the ideal adiabatic flame temperature (0, 1].

0.95
nozzle_loss_model NozzleLossModel | None

Nozzle loss model.

None
Source code in machwave/models/motors/solid.py
def __init__(
    self,
    grain: grain.Grain,
    propellant: propellants.SolidPropellant,
    thrust_chamber: thrust_chamber.SolidMotorThrustChamber,
    combustion_efficiency: float = 0.95,
    nozzle_loss_model: nozzle_losses.NozzleLossModel | None = None,
) -> None:
    """
    Initialize a solid rocket motor.

    Args:
        grain: Grain geometry configuration.
        propellant: Solid propellant properties.
        thrust_chamber: Thrust chamber model.
        combustion_efficiency: Ratio of the actual flame temperature to the ideal
            adiabatic flame temperature (0, 1].
        nozzle_loss_model: Nozzle loss model.
    """
    super().__init__(
        propellant,
        thrust_chamber,
        combustion_efficiency,
        nozzle_loss_model=nozzle_loss_model
        or nozzle_losses.presets.spp1975_solid_loss_model(),
    )

    self.grain = grain
    self.propellant: propellants.SolidPropellant = propellant

get_free_chamber_volume(propellant_volume)

Return the chamber volume without any propellant.

Parameters:

Name Type Description Default
propellant_volume float

Propellant volume [m^3].

required

Returns:

Type Description
float

Free chamber volume [m^3].

Source code in machwave/models/motors/solid.py
def get_free_chamber_volume(self, propellant_volume: float) -> float:
    """
    Return the chamber volume without any propellant.

    Args:
        propellant_volume: Propellant volume [m^3].

    Returns:
        Free chamber volume [m^3].
    """
    return (
        self.thrust_chamber.combustion_chamber.internal_volume - propellant_volume
    )