Skip to content

Simulation

Main entry point for running internal ballistics simulations. InternalBallisticsSimulation takes a motor model and simulation parameters (time step, igniter pressure, external pressure), then marches through time using an RK4 solver to produce a complete motor state with time-series data for thrust, chamber pressure, propellant mass, efficiency losses, and more.

The returned MotorState object (see states) contains all computed arrays for post-processing or adapter export.

machwave.simulation

InternalBallisticsSimulation

Internal ballistics simulation class.

Attributes:

Name Type Description
motor Motor

Motor object.

params InternalBallisticsSimulationParams

Simulation parameters.

t ndarray

Array of time values.

motor_state MotorState | None

Motor state object.

Source code in machwave/simulation.py
class InternalBallisticsSimulation:
    """Internal ballistics simulation class.

    Attributes:
        motor: Motor object.
        params: Simulation parameters.
        t: Array of time values.
        motor_state: Motor state object.
    """

    def __init__(
        self,
        motor: Motor,
        params: InternalBallisticsSimulationParams,
    ) -> None:
        self.motor: Motor = motor
        self.params: InternalBallisticsSimulationParams = params
        self.t: np.ndarray = np.array([0.0])
        self.motor_state: MotorState | None = None

    def get_motor_state(self) -> MotorState:
        """
        Returns the motor state object based on the type of the motor.
        """
        motor_state_class = _get_motor_state_class(self.motor)
        return motor_state_class(
            motor=self.motor,
            initial_pressure=self.params.igniter_pressure,
            initial_atmospheric_pressure=self.params.external_pressure,
            other_losses=self.params.other_losses,
        )

    def run(self) -> tuple[np.ndarray, MotorState]:
        """
        Runs the main loop of the simulation, returning the time array and
        the motor state object.
        """
        self.motor_state = self.get_motor_state()

        d_t = self.params.d_t
        external_pressure = self.params.external_pressure
        t_values: list[float] = [0.0]

        while not self.motor_state.end_thrust:
            t_values.append(t_values[-1] + d_t)
            self.motor_state.run_timestep(d_t, external_pressure)

        self.t = np.asarray(t_values)
        self.motor_state.convert_simulation_arrays_to_numpy()

        return (self.t, self.motor_state)

    def print_results(self) -> None:
        """
        Prints the results of the simulation.
        """
        if self.motor_state is None:
            print("No motor state results available. Try running the simulation first.")
            return

        print("\nINTERNAL BALLISTICS SIMULATION RESULTS")
        self.motor_state.print_results()

get_motor_state()

Returns the motor state object based on the type of the motor.

Source code in machwave/simulation.py
def get_motor_state(self) -> MotorState:
    """
    Returns the motor state object based on the type of the motor.
    """
    motor_state_class = _get_motor_state_class(self.motor)
    return motor_state_class(
        motor=self.motor,
        initial_pressure=self.params.igniter_pressure,
        initial_atmospheric_pressure=self.params.external_pressure,
        other_losses=self.params.other_losses,
    )

print_results()

Prints the results of the simulation.

Source code in machwave/simulation.py
def print_results(self) -> None:
    """
    Prints the results of the simulation.
    """
    if self.motor_state is None:
        print("No motor state results available. Try running the simulation first.")
        return

    print("\nINTERNAL BALLISTICS SIMULATION RESULTS")
    self.motor_state.print_results()

run()

Runs the main loop of the simulation, returning the time array and the motor state object.

Source code in machwave/simulation.py
def run(self) -> tuple[np.ndarray, MotorState]:
    """
    Runs the main loop of the simulation, returning the time array and
    the motor state object.
    """
    self.motor_state = self.get_motor_state()

    d_t = self.params.d_t
    external_pressure = self.params.external_pressure
    t_values: list[float] = [0.0]

    while not self.motor_state.end_thrust:
        t_values.append(t_values[-1] + d_t)
        self.motor_state.run_timestep(d_t, external_pressure)

    self.t = np.asarray(t_values)
    self.motor_state.convert_simulation_arrays_to_numpy()

    return (self.t, self.motor_state)

InternalBallisticsSimulationParams dataclass

Parameters for an internal ballistics simulation.

Attributes:

Name Type Description
d_t float

Time step.

igniter_pressure float

Igniter pressure.

external_pressure float

External pressure.

other_losses float

Additional losses not covered by specific loss mechanisms, as a fraction in [0, 1] (e.g. 0.12 for 12%).

Source code in machwave/simulation.py
@dataclass
class InternalBallisticsSimulationParams:
    """Parameters for an internal ballistics simulation.

    Attributes:
        d_t: Time step.
        igniter_pressure: Igniter pressure.
        external_pressure: External pressure.
        other_losses: Additional losses not covered by specific loss mechanisms,
            as a fraction in [0, 1] (e.g. 0.12 for 12%).
    """

    d_t: float
    igniter_pressure: float
    external_pressure: float
    other_losses: float = 0.12