Skip to content

Conversation

Copy link

Copilot AI commented Nov 14, 2025

Pull request type

  • Code changes (bugfix, features)
  • Code maintenance (refactoring, formatting, tests)

Checklist

  • Tests for the changes have been added (if needed)
  • Docs have been reviewed and added / updated
  • Lint (black rocketpy/ tests/) has passed locally
  • All tests (pytest tests -m slow --runslow) have passed locally
  • CHANGELOG.md has been updated (if relevant)

Current behavior

Drag coefficients are limited to 1D functions of Mach number. CFD simulations typically produce drag data varying with Reynolds number and angle of attack, which cannot be properly represented.

New behavior

Drag coefficients now support N-dimensional structured grids via Function.from_grid(). Flight simulations automatically calculate and pass Reynolds number (from velocity, density, viscosity, rocket diameter) and angle of attack (from freestream velocity vectors in body frame) to multi-dimensional drag functions.

Implementation

Function Class (rocketpy/mathutils/function.py)

  • Added from_grid() class method using scipy.interpolate.RegularGridInterpolator
  • Added 'linear_grid' interpolation type with edge clamping (no extrapolation beyond bounds)
  • Grid data stored as flattened array for serialization compatibility

Flight Class (rocketpy/simulation/flight.py)

  • Added __get_drag_coefficient() helper detecting function dimensionality
  • Calculates Re = ρVD/μ and α from body-frame velocities during integration
  • Updated udot_rail1(), u_dot(), u_dot_generalized() to use helper

Rocket Class (rocketpy/rocket/rocket.py)

  • Preserves Function objects when passed as drag coefficients (previously wrapped in 1D Function)

Usage Example

import numpy as np
from rocketpy import Function, Rocket

# Create 3D drag data from CFD
mach = np.array([0.0, 0.5, 1.0, 1.5, 2.0])
reynolds = np.array([1e5, 5e5, 1e6])
alpha = np.array([0.0, 2.0, 4.0, 6.0])  # degrees

M, Re, A = np.meshgrid(mach, reynolds, alpha, indexing='ij')
cd_data = 0.3 + 0.1*M - 1e-7*Re + 0.01*A

# Create structured grid function
drag_func = Function.from_grid(
    cd_data, 
    [mach, reynolds, alpha],
    inputs=['Mach', 'Reynolds', 'Alpha'],
    outputs='Cd'
)

# Use directly in Rocket - Flight automatically handles M, Re, α
rocket = Rocket(..., power_off_drag=drag_func, power_on_drag=drag_func)

Testing

  • 7 unit tests for Function.from_grid() covering 1D/2D/3D grids, extrapolation, validation
  • 3 integration tests for 3D drag in flight simulations
  • All 593 existing tests pass (full backward compatibility)

Breaking change

  • No

Existing 1D drag curves (Mach only) work unchanged. Multi-dimensional support is opt-in via from_grid().

Additional information

Resolves #874

CodeQL security scan: 0 alerts

Original prompt

This section details on the original issue you should resolve

<issue_title>ENH: Drag curve as a function of Re and alpha as well</issue_title>
<issue_description>Is your feature request related to a problem? Please describe.

As of now drag curve is a function of speed (or mach number). Since a lot of rocketeers use CFD simulations, it is expected that drag values won't be just a function of mach number. Drag of any body moving in fluid can depend on many major parameters. Some of them are listed below:

  • Reynolds Number (Re)
  • Angle of Attack (alpha)
  • Altitude/Air Properties
  • Rocket Geometry/Shape
  • Surface Roughness

Re accounts for the viscous effects of the flow (skin friction vs. pressure drag). Reynolds number depends on velocity, characteristic length, air viscosity, and density, and is crucial for modeling drag at low speeds and during laminar-turbulent transitions. Non-zero angles of attack change the effective cross-sectional area and cause flow separation or vortex formation, increasing drag. Altitude or atmospheric variation can be handled by RocketPy separately to update Re or atmospheric data rather than being built directly into the drag curve.
Drag could be input as Cd(M, α) or Cd(M, Re, α).

Describe the solution you'd like

  1. A multidimensional array implementation of Cd=f(M,Re,α) in Rocket Class.
  2. Extension of drag_coeff in flight class to allow multiple params as input - M, Re and alpha. Probably implement new get_value_opt like function specifically for this.
  3. Check if current interpolation and extrapolation methods of the Function class are applicable in case of 2D/3D arrays. If not then update the same.
  4. Ensure backwards compatibility to still allow for use of Cd=f(M).

Additional context

It does not make sense that the drag curve will be given as an input of Cd=f(Re) or Cd=f(α). Physically these are not capturing the entire flow physics at the same accuracy at which Cd=f(M) does as mach number based effects like shock wave propagation become more important in rocket flights. May be still allow for single array functionality with Re and α but provide a note that the results may not be accurate!</issue_description>

<agent_instructions>Here is a specific, technical prompt you can use to delegate this issue to the GitHub Copilot agent. This prompt directs it to the correct implementation strategy we discussed (enhancing the Function class).


Optional Prompt for GitHub Copilot

Here is a specific prompt to guide the implementation for Issue #874.

1. Core Objective:
Implement the enhancement described in issue #874. The goal is to allow the drag coefficient Cd to be defined as a 3D function of Mach (M), Reynolds number (Re), and Angle of Attack ($\alpha$).

2. Implementation Location:
The primary changes must be made within the rocketpy.Function class (in rocketpy/function.py). This is not just a change to the Flight or Rocket class; the Function class itself must be enhanced to handle N-dimensional structured grid data.

3. Add New Interpolation Method:
The current shepard interpolation is inefficient for structured CFD grids.

  • Add a new interpolation option (e.g., interpolation='linear_grid' or interpolation='grid') to the Function class __init__.
  • This new method MUST use scipy.interpolate.RegularGridInterpolator as its backend. You will need to import this from scipy.interpolate.
  • The Function class state should store the initialized RegularGridInterpolator object to be called later.

4. Add New Function.from_grid() Class Method:
Manually creating a flattened list of points is impractical for users.

  • Create a new class method: @classmethod def from_grid(cls, grid_data, axes, inputs, output, interpolation='linear_grid', **kwargs).
  • This method will accept:
    • grid_data: An N-dimensional NumPy array (e.g., a 3D array for $C_d$).
    • axes: A list of 1D arrays representing the axes of the grid (e.g., [M_axis, Re_axis, A_axis]).
    • inputs: A list of strings, e.g., ['Mach', 'Reynolds', 'Alpha'].
    • output: A string, e.g., 'Cd'.
  • Inside this method, you will initialize the scipy.interpolate.RegularGridInterpolator with the provided axes and grid_data and store it in the new Function object.

5. Handle Extrapolation (Crucial):
The new grid interpolation must clamp to the edge (i.e., use the nearest edge value) for out-of-bounds requests. It should not extrapolate.

  • When initializing RegularGridInterpolator, set bounds_error=False.
  • The fill_value should be set to None, which (when bounds_error=False) causes the interpolator to use the edge values for out-of-bounds points.

6. Update Flight Class:
The Flight class (likely in flight.py or related files) must be modified to use this new function.

  • The flight simulation loop needs to detect the type of drag function it has.
  • If the `rocket.aerodynamic_surfaces.dra...

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@Gui-FernandesBR Gui-FernandesBR changed the base branch from master to develop November 14, 2025 19:33
Copilot AI changed the title [WIP] Enhance drag curve to include Re and alpha variables ENH: Add multi-dimensional drag coefficient support (Cd as function of M, Re, α) Nov 14, 2025
Copilot finished work on behalf of Gui-FernandesBR November 14, 2025 20:04
@aZira371
Copy link
Collaborator

aZira371 commented Nov 15, 2025

The code implementation is as I planned it to be done. There might be a slight edge case which should be addressed in regular grid interpolator unit tests or with warning: that the grid was not sorted in ascending order as intended. This can happen with repeated values in the grid. Apart from that the changes are okay to be merged! @Gui-FernandesBR @copilot

@Gui-FernandesBR Gui-FernandesBR force-pushed the copilot/enhance-drag-curve-functionality branch from 356e14a to b621a16 Compare November 15, 2025 16:20
- MNT: velocity_body was not being used in get_drag_coefficient, removed it as an input
@aZira371 aZira371 self-assigned this Nov 15, 2025
@aZira371
Copy link
Collaborator

@Gui-FernandesBR Is there a way to see this branch on VSC? I am unable to access it there. It is not being listed as a remote branch. I think one of the previous lint errors was related to the new grid method being too big in function.py. It should be ideally broken down into helper functions or pylint has to be disabled for it.

… test_multidim_drag.py

-MNT:  removed unused velocity in body frame parameter requirement from all instances of get_drag_coefficient in flight.py

- MNT: corrected docstring for get_value_opt_grid in function.py

- MNT: shifted import of classes before the definition of functions in test_multidim_drag.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

ENH: Drag curve as a function of Re and alpha as well

3 participants