waterrocketpy.analysis.energy_breakdown¶
EnergyComponents
dataclass
¶
Container for energy breakdown results.
Source code in waterrocketpy/analysis/energy_breakdown.py
@dataclass
class EnergyComponents:
"""Container for energy breakdown results."""
time: np.ndarray
# Internal energy
air_internal_energy: np.ndarray
# Rocket system energy
rocket_kinetic_energy: np.ndarray
rocket_potential_energy: np.ndarray
water_in_kinetic_energy: np.ndarray
water_in_potential_energy: np.ndarray
# Expelled fluid energy (cumulative)
water_out_kinetic_energy: np.ndarray
water_out_potential_energy: np.ndarray
air_out_kinetic_energy: np.ndarray
air_out_potential_energy: np.ndarray
# Energy losses (cumulative)
drag_energy_loss: np.ndarray
# Total energy accounting
total_initial_energy: float
total_final_energy: np.ndarray
energy_conservation_error: np.ndarray
# Summary values
max_kinetic_energy: float
max_potential_energy: float
total_drag_loss: float
total_expelled_energy: float
tenergy_breakdown(flight_data, rocket_params)
¶
Perform comprehensive energy breakdown analysis of water rocket flight.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
flight_data |
FlightData object from simulation |
required | |
rocket_params |
Dict[str, Any] |
Rocket configuration parameters |
required |
Returns:
| Type | Description |
|---|---|
EnergyComponents |
EnergyComponents object with detailed energy analysis |
Source code in waterrocketpy/analysis/energy_breakdown.py
def tenergy_breakdown(
flight_data, rocket_params: Dict[str, Any]
) -> EnergyComponents:
"""
Perform comprehensive energy breakdown analysis of water rocket flight.
Args:
flight_data: FlightData object from simulation
rocket_params: Rocket configuration parameters
Returns:
EnergyComponents object with detailed energy analysis
"""
# Extract data arrays
time = flight_data.time
altitude = flight_data.altitude
velocity = flight_data.velocity
water_mass = flight_data.water_mass
air_mass = flight_data.air_mass
pressure = flight_data.pressure
air_temperature = flight_data.air_temperature
drag = flight_data.drag
thrust = flight_data.thrust
# Calculate rocket mass components
m_empty = rocket_params["m_empty"]
total_mass = m_empty + water_mass + air_mass
# 1. Internal Energy of Pressurized Air
# Using U = m * cv * T for internal energy
air_internal_energy = air_mass * AIR_SPECIFIC_HEAT_CV * air_temperature
# 2. Kinetic Energy of Rocket System
rocket_kinetic_energy = 0.5 * total_mass * velocity**2
# 3. Potential Energy of Rocket System
rocket_potential_energy = total_mass * GRAVITY * altitude
# 4. Kinetic Energy of Water Inside Rocket
water_in_kinetic_energy = 0.5 * water_mass * velocity**2
# 5. Potential Energy of Water Inside Rocket
water_in_potential_energy = water_mass * GRAVITY * altitude
# 6. Energy of Expelled Water (cumulative integration)
water_out_kinetic_energy = np.zeros_like(time)
water_out_potential_energy = np.zeros_like(time)
# Calculate expelled water energy by integrating over time
for i in range(1, len(time)):
dt = time[i] - time[i - 1]
# Water mass flow rate (negative since mass is decreasing) NOOOO its
# the other way around! leaving water / air is defined as positive in
# the simulation
if i < len(flight_data.water_mass_flow_rate):
dm_water_dt = flight_data.water_mass_flow_rate[i]
else:
dm_water_dt = 0.0
if dm_water_dt > 0: # Water is being expelled
# Estimate water exhaust velocity
if flight_data.water_exhaust_speed[i] is not None:
v_exhaust = flight_data.water_exhaust_speed[i]
else:
# Fallback: estimate from thrust and mass flow rate
if dm_water_dt > 0:
v_exhaust = (
thrust[i] / dm_water_dt if dm_water_dt > 1e-10 else 0.0
)
else:
v_exhaust = 0.0
# Energy carried away by expelled water
dE_kin_water = 0.5 * dm_water_dt * v_exhaust**2 * dt
dE_pot_water = dm_water_dt * GRAVITY * altitude[i] * dt
water_out_kinetic_energy[i] = (
water_out_kinetic_energy[i - 1] + dE_kin_water
)
water_out_potential_energy[i] = (
water_out_potential_energy[i - 1] + dE_pot_water
)
else:
water_out_kinetic_energy[i] = water_out_kinetic_energy[i - 1]
water_out_potential_energy[i] = water_out_potential_energy[i - 1]
# 7. Energy of Expelled Air (cumulative integration)
air_out_kinetic_energy = np.zeros_like(time)
air_out_potential_energy = np.zeros_like(time)
for i in range(1, len(time)):
dt = time[i] - time[i - 1]
# Air mass flow rate
if i < len(flight_data.air_mass_flow_rate):
dm_air_dt = flight_data.air_mass_flow_rate[i]
else:
dm_air_dt = 0.0
if dm_air_dt > 0: # Air is being expelled
# Estimate air exhaust velocity -> leaving water / air is defined
# as positive in the simulation
if flight_data.air_exhaust_speed[i] is not None:
v_exhaust_air = flight_data.air_exhaust_speed[i]
else:
# Fallback: estimate from thrust and mass flow rate
if dm_air_dt > 0:
v_exhaust_air = (
thrust[i] / dm_air_dt if dm_air_dt > 1e-10 else 0.0
)
else:
v_exhaust_air = 0.0
# Energy carried away by expelled air
dE_kin_air = 0.5 * dm_air_dt * v_exhaust_air**2 * dt
dE_pot_air = dm_air_dt * GRAVITY * altitude[i] * dt
air_out_kinetic_energy[i] = (
air_out_kinetic_energy[i - 1] + dE_kin_air
)
air_out_potential_energy[i] = (
air_out_potential_energy[i - 1] + dE_pot_air
)
else:
air_out_kinetic_energy[i] = air_out_kinetic_energy[i - 1]
air_out_potential_energy[i] = air_out_potential_energy[i - 1]
# 8. Energy Loss Due to Drag (cumulative)
drag_energy_loss = np.zeros_like(time)
for i in range(1, len(time)):
dt = time[i] - time[i - 1]
# Energy lost to drag = drag force * distance = drag * velocity * dt
dE_drag = abs(drag[i]) * abs(velocity[i]) * dt
drag_energy_loss[i] = drag_energy_loss[i - 1] + dE_drag
# 9. Calculate Initial Total Energy
# Initial energy is stored as internal energy in pressurized air
initial_air_volume = rocket_params["V_bottle"] * (
1 - rocket_params["water_fraction"]
)
initial_air_mass = (rocket_params["P0"] * initial_air_volume) / (
287.0 * INITIAL_TEMPERATURE
) # Using ideal gas law
total_initial_energy = (
initial_air_mass * AIR_SPECIFIC_HEAT_CV * INITIAL_TEMPERATURE
)
# 10. Energy Conservation Check
# Total energy at time t should equal:
# Internal + Kinetic + Potential + Expelled + Losses
total_final_energy = (
air_internal_energy
+ rocket_kinetic_energy
+ rocket_potential_energy
+ water_out_kinetic_energy
+ water_out_potential_energy
+ air_out_kinetic_energy
+ air_out_potential_energy
+ drag_energy_loss
)
energy_conservation_error = (
abs(total_final_energy - total_initial_energy)
/ total_initial_energy
* 100
)
# Calculate summary values
max_kinetic_energy = np.max(rocket_kinetic_energy)
max_potential_energy = np.max(rocket_potential_energy)
total_drag_loss = drag_energy_loss[-1]
total_expelled_energy = (
water_out_kinetic_energy[-1]
+ water_out_potential_energy[-1]
+ air_out_kinetic_energy[-1]
+ air_out_potential_energy[-1]
)
return EnergyComponents(
time=time,
air_internal_energy=air_internal_energy,
rocket_kinetic_energy=rocket_kinetic_energy,
rocket_potential_energy=rocket_potential_energy,
water_in_kinetic_energy=water_in_kinetic_energy,
water_in_potential_energy=water_in_potential_energy,
water_out_kinetic_energy=water_out_kinetic_energy,
water_out_potential_energy=water_out_potential_energy,
air_out_kinetic_energy=air_out_kinetic_energy,
air_out_potential_energy=air_out_potential_energy,
drag_energy_loss=drag_energy_loss,
total_initial_energy=total_initial_energy,
total_final_energy=total_final_energy,
energy_conservation_error=energy_conservation_error,
max_kinetic_energy=max_kinetic_energy,
max_potential_energy=max_potential_energy,
total_drag_loss=total_drag_loss,
total_expelled_energy=total_expelled_energy,
)