Skip to content

Commit e4053ac

Browse files
committed
TST: test_multidim_drag.py
- TST: Added integration-level check to verify the flight simulation actually uses alpha when evaluating multi dim drag coeff. - TST: utilized pytest fixtures where possible.
1 parent 74fe825 commit e4053ac

File tree

1 file changed

+109
-33
lines changed

1 file changed

+109
-33
lines changed

tests/integration/test_multidim_drag.py

Lines changed: 109 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,27 @@
22

33
import numpy as np
44

5-
from rocketpy import Environment, Flight, Function, Rocket, SolidMotor
5+
from rocketpy import Flight, Function, Rocket
66

77

8-
def test_flight_with_1d_drag(example_plain_env, calisto):
8+
def test_flight_with_1d_drag(flight_calisto):
99
"""Test that flights with 1D drag curves still work (backward compatibility)."""
1010

11-
flight = Flight(
12-
rocket=calisto,
13-
environment=example_plain_env,
14-
rail_length=5.2,
15-
inclination=85,
16-
heading=0,
17-
)
11+
# `flight_calisto` is a fixture that already runs the simulation
12+
flight = flight_calisto
1813

1914
# Check that flight completed successfully
2015
assert flight.t_final > 0
2116
assert flight.apogee > 0
2217
assert flight.apogee_time > 0
2318

2419

25-
def test_flight_with_3d_drag_basic():
20+
def test_flight_with_3d_drag_basic(example_plain_env, cesaroni_m1670):
2621
"""Test that a simple 3D drag function works."""
27-
# Create environment
28-
env = Environment(gravity=9.81)
22+
# Use fixtures for environment and motor
23+
env = example_plain_env
2924
env.set_atmospheric_model(type="standard_atmosphere")
30-
31-
# Create motor with simple constant thrust
32-
motor = SolidMotor(
33-
thrust_source=lambda t: 2000 if t < 3 else 0,
34-
burn_time=3.0,
35-
nozzle_radius=0.033,
36-
dry_mass=1.815,
37-
dry_inertia=(0.125, 0.125, 0.002),
38-
center_of_dry_mass_position=0.317,
39-
grains_center_of_mass_position=0.397,
40-
grain_number=5,
41-
grain_separation=0.005,
42-
grain_density=1815,
43-
grain_outer_radius=0.033,
44-
grain_initial_inner_radius=0.015,
45-
grain_initial_height=0.120,
46-
nozzle_position=0,
47-
throat_radius=0.011,
48-
)
25+
motor = cesaroni_m1670
4926

5027
# Create 3D drag
5128
mach = np.array([0.0, 0.5, 1.0, 1.5, 2.0])
@@ -97,7 +74,7 @@ def test_flight_with_3d_drag_basic():
9774
assert hasattr(flight, "angle_of_attack")
9875

9976

100-
def test_3d_drag_with_varying_alpha():
77+
def test_3d_drag_with_varying_alpha(example_plain_env, cesaroni_m1670):
10178
"""Test that 3D drag responds to angle of attack changes."""
10279
# Create drag function with strong alpha dependency
10380
mach = np.array([0.0, 0.5, 1.0, 1.5])
@@ -116,11 +93,110 @@ def test_3d_drag_with_varying_alpha():
11693
outputs="Cd",
11794
)
11895

119-
# Test at different angles of attack
96+
# Test at different angles of attack (direct function call)
12097
# At zero alpha, Cd should be lower
12198
cd_0 = drag_func(0.8, 5e5, 0.0)
12299
cd_10 = drag_func(0.8, 5e5, 10.0)
123100

124101
# Cd should increase with alpha
125102
assert cd_10 > cd_0
126103
assert cd_10 - cd_0 > 0.2 # Should show significant difference
104+
105+
# --- Integration test: verify flight uses alpha-dependent Cd ---
106+
# Create a flat (alpha-agnostic) drag by averaging over alpha
107+
cd_flat = cd_data.mean(axis=2)
108+
drag_flat = Function.from_grid(
109+
cd_flat, [mach, reynolds], inputs=["Mach", "Reynolds"], outputs="Cd",
110+
)
111+
112+
# Use fixtures for environment and motor
113+
env = example_plain_env
114+
env.set_atmospheric_model(type="standard_atmosphere")
115+
motor = cesaroni_m1670
116+
117+
# Build two rockets: one that uses alpha-sensitive drag, one flat
118+
rocket_alpha = Rocket(
119+
radius=0.0635,
120+
mass=16.24,
121+
inertia=(6.321, 6.321, 0.034),
122+
power_off_drag=drag_func,
123+
power_on_drag=drag_func,
124+
center_of_mass_without_motor=0,
125+
coordinate_system_orientation="tail_to_nose",
126+
)
127+
rocket_alpha.set_rail_buttons(0.2, -0.5, 30)
128+
rocket_alpha.add_motor(motor, position=-1.255)
129+
130+
rocket_flat = Rocket(
131+
radius=0.0635,
132+
mass=16.24,
133+
inertia=(6.321, 6.321, 0.034),
134+
power_off_drag=drag_flat,
135+
power_on_drag=drag_flat,
136+
center_of_mass_without_motor=0,
137+
coordinate_system_orientation="tail_to_nose",
138+
)
139+
rocket_flat.set_rail_buttons(0.2, -0.5, 30)
140+
rocket_flat.add_motor(motor, position=-1.255)
141+
142+
# Run flights
143+
flight_alpha = Flight(
144+
rocket=rocket_alpha,
145+
environment=env,
146+
rail_length=5.2,
147+
inclination=85,
148+
heading=0,
149+
)
150+
151+
flight_flat = Flight(
152+
rocket=rocket_flat,
153+
environment=env,
154+
rail_length=5.2,
155+
inclination=85,
156+
heading=0,
157+
)
158+
159+
# Flights should both launch
160+
assert flight_alpha.apogee > 100
161+
assert flight_flat.apogee > 100
162+
163+
# The two rockets should behave differently since one depends on alpha
164+
# while the other uses a flat-averaged Cd. Do not assume which direction
165+
# is larger (depends on encountered alpha vs averaged alpha) but ensure
166+
# the apogees differ.
167+
assert flight_alpha.apogee != flight_flat.apogee
168+
169+
# Additionally, sample Cd during flight from aerodynamic state and
170+
# compare values computed from each rocket's drag function at the
171+
# same time index to ensure alpha actually affects the evaluated Cd.
172+
# Use mid-ascent index (avoid t=0). Find a time index where speed > 5 m/s
173+
speeds = flight_alpha.free_stream_speed[:, 1]
174+
times = flight_alpha.time
175+
idx_candidates = np.where(speeds > 5)[0]
176+
assert idx_candidates.size > 0
177+
idx = idx_candidates[len(idx_candidates) // 2]
178+
t_sample = times[idx]
179+
180+
mach_sample = flight_alpha.mach_number.get_value_opt(t_sample)
181+
rho_sample = flight_alpha.density.get_value_opt(t_sample)
182+
mu_sample = flight_alpha.dynamic_viscosity.get_value_opt(t_sample)
183+
V_sample = flight_alpha.free_stream_speed.get_value_opt(t_sample)
184+
reynolds_sample = rho_sample * V_sample * (2 * rocket_alpha.radius) / mu_sample
185+
alpha_sample = flight_alpha.angle_of_attack.get_value_opt(t_sample)
186+
187+
cd_alpha_sample = rocket_alpha.power_on_drag.get_value_opt(
188+
mach_sample, reynolds_sample, alpha_sample
189+
)
190+
cd_flat_sample = rocket_flat.power_on_drag.get_value_opt(
191+
mach_sample, reynolds_sample
192+
)
193+
194+
# Alpha-sensitive Cd should differ from the flat Cd at the sampled time
195+
assert cd_alpha_sample != cd_flat_sample
196+
197+
# Ensure the sign of the Cd difference is consistent with the apogee
198+
# ordering: larger Cd -> lower apogee
199+
if cd_alpha_sample > cd_flat_sample:
200+
assert flight_alpha.apogee < flight_flat.apogee
201+
else:
202+
assert flight_alpha.apogee > flight_flat.apogee

0 commit comments

Comments
 (0)