Boundary Layer Transition (aerodynamics/boundary-layer/boundary-layer-transition)
Use when you must predict where the laminar boundary layer turns
turbulent on a two-dimensional body from its edge-velocity
distribution. This leaf implements the standard integral estimate:
grow the laminar layer with the Thwaites relation to get the momentum
thickness theta at each station, then apply the Michel empirical
criterion on the local Reynolds numbers to locate the natural
transition point. The logic is pure Python, stdlib only, and covers a
clean two-dimensional surface (no roughness, sweep or suction inputs
and no Tollmien-Schlichting wave-growth integration; the Michel
criterion replaces an eN envelope). It pairs with
aerodynamics/boundary-layer/boundary-layer-theory, which owns the
flat-plate thickness and skin-friction correlations on either side of
the transition.
Domain quick reference
Edge-velocity Reynolds number: Re_x = Ue(x) * x / nu with Ue the
inviscid edge velocity and nu the kinematic viscosity (SI units
throughout, m, m/s, m2/s).
Thwaites integral relation for the laminar momentum thickness:
theta(x)^2 = THWAITES_C * nu / Ue(x)^6 * integral_0^x Ue(xi)^5 d(xi)
with THWAITES_C = 0.45. The integral is evaluated cumulatively with
the trapezoid rule over the supplied stations; the segment from the
leading edge (x = 0) to the first station keeps Ue at its
first-station value, which makes the constant-velocity flat plate
exact.
Momentum-thickness Reynolds number: Re_theta = Ue * theta / nu.
Michel transition criterion (empirical):
Re_theta,tr = MICHEL_A * (1 + MICHEL_B / Re_x) * Re_x**MICHEL_P
with MICHEL_A = 1.174, MICHEL_B = 22400.0, MICHEL_P = 0.46.
Transition onset occurs at the first station where Re_theta reaches
the threshold; the margin m = Re_theta - threshold crosses zero
there.
Flat-plate exact solution (verification helper): with constant Ue the
Thwaites relation closes to Re_theta = sqrt(0.45) * sqrt(Re_x) =
0.6708 * sqrt(Re_x), so theta = 0.6708 * sqrt(Re_x) * nu / Ue.
Natural-transition distance on a smooth flat plate follows from the
Michel crossing, typically Re_x ~ 1.7e6 at low free-stream
turbulence, an order of magnitude beyond the textbook 5e5 landmark
that boundary-layer-theory quotes for the onset of instability.
NACA TR-824 frames the boundary-layer context; the relations above
are standard engineering methodology, summary-only.
Workflow
- Assemble the station grid: xs (m) strictly increasing and the edge
velocities ues (m/s) at each station, equal length, all ue > 0.
- Grow the laminar layer with momentum_thickness_profile(xs, ues,
nu): returns the Thwaites theta at every station.
- Build the Reynolds history with re_theta_profile(xs, ues,
theta_list, nu) and the Michel threshold with
michel_threshold(re_x) at each station.
- Run the one-call sweep transition_location(xs, ues, nu): returns
theta_list, re_theta_list, criterion_margin_list, x_transition
(first station where the margin is non-negative, or None), the
transition_index and interp_x_transition (linear interpolation of
the margin to zero between the bracketing stations).
- For a quick flat-plate check use flat_plate_transition(nu, ue,
x_max), the analytic natural-transition distance on a
constant-velocity plate, or michel_criterion(re_x, re_theta) for a
single point test.
- Confirm the deterministic checks with the contract test
scripts/test_boundary_layer_transition.py.
Worked example
Smooth flat plate in low-turbulence flow: nu = 1.46e-5 m2/s, Ue = 30
m/s.
- Momentum thickness from momentum_thickness_profile over x = 0.25,
1.0, 2.0 m: theta = 2.3399e-4, 4.6797e-4, 6.6182e-4 m. At x = 1 m
the value matches the exact flat-plate value 0.6708 * sqrt(2.0548e6) * nu / Ue
= 4.680e-4 m to six digits, and Re_theta(1 m) = 961.6 equals 0.6708
- sqrt(Re_x) (the trapezoid Thwaites integral is exact for constant
Ue).
- Michel threshold at x = 1 m: michel_threshold(2.0548e6) = 951.15,
so the margin there is 961.6 - 951.15 = +10.44. On the coarse grid
the margins are -38.16 (x = 0.25 m), +10.44 (x = 1.0 m) and +58.60
(x = 2.0 m): transition_location reports x_transition = 1.0 m
(station value) with interp_x_transition = 0.8389 m between the
bracketing stations.
- Exact-solution helper: flat_plate_transition(1.46e-5, 30.0, 2.0)
returns x_tr = 0.8126 m (inside the 0.6-1.1 m band), i.e.
Re_x,tr = 1.670e6 with Re_theta at the crossing = 866.8 (inside
800-1100). The margin is negative just below x_tr and non-negative
at it, as expected for a first-crossing scan.
Verification
- Confirm momentum_thickness_profile on the three-station flat plate
is monotonic and matches 0.6708 * sqrt(Re_x) * nu / Ue within 1e-6
relative at every station.
- Confirm the flat-plate Re_theta identity re_theta_profile(...)
equals 0.6708 * sqrt(Re_x) within 1e-9 relative.
- Confirm flat_plate_transition(1.46e-5, 30.0, 2.0) lies in 0.6-1.1 m
and the Re_theta at the crossing lies in 800-1100.
- Confirm ValueError rejection of fewer than two stations,
unequal-length xs/ues, x below zero or not strictly increasing,
ue <= 0, nu <= 0, re_x <= 0 and re_theta < 0.
- Confirm determinism: repeated calls on identical inputs return
identical results.
- Run the contract test offline: python3
scripts/test_boundary_layer_transition.py (32 tests, deterministic,
under 20 s).
Related leaves
- aerodynamics/boundary-layer/boundary-layer-theory: the laminar and
turbulent flat-plate thickness and skin-friction correlations that
bookend the transition point.
- aerodynamics/airfoil/xfoil-analysis: viscous airfoil analysis that
can supply the edge-velocity distribution and an independent
transition estimate for comparison.
- aerodynamics/drag-polars/parasite-drag: uses the laminar versus
turbulent split downstream of transition for wetted-area drag.
Pitfalls
- Feeding a grid that is not strictly increasing, starts below zero, or
pairs xs and ues of unequal length: the Thwaites integral is only
exact for the constant-velocity plate; the module rejects such grids
with ValueError, so validate the station list before calling.
- Quoting the station value as the transition location: on the coarse
grid transition_location reports x_transition = 1.0 m while the
linear interpolation of the margin places the crossing at 0.8389 m;
use interp_x_transition for the location estimate.
- Confusing the Michel natural-transition distance with the 5e5
instability-onset landmark: on a smooth flat plate the criterion
crosses near Re_x ~ 1.7e6, an order of magnitude beyond the
boundary-layer-theory textbook value for the onset of instability.
- Applying the model to forced or roughness-triggered transition: this
leaf covers clean two-dimensional natural transition only; the Michel
criterion replaces an eN envelope and takes no roughness, sweep or
suction input.
- Treating a never-crossed margin as a zero-length run: when the
criterion is never met, x_transition is None and the body stays
laminar over the supplied stations - report that outcome rather than
forcing a crossing.
- Ignoring the margin sign convention at the first station: the sweep
returns the first station with non-negative margin, so the bracketing
stations and the sign flip define the crossing, not the station where
the margin is largest.
Behavior contract (gate 3)
Run the deterministic contract test (stdlib unittest, offline):
python3 scripts/test_boundary_layer_transition.py
The test covers the Thwaites momentum thickness against the flat-plate
exact solution, the worked-example theta at x = 1 m (4.680e-4 m), the
Michel threshold and criterion logic including the equality boundary,
the transition sweep bounds (x_tr in 0.6-1.1 m, Re_theta in 800-1100)
with the station versus interpolated crossing distinction, the margin
sign flip across the crossing, the never-crossed and first-station-
crossed cases, the exact-solution flat_plate_transition helper and its
bounds, ValueError rejection of every non-physical input in the
validation list, and determinism.
Compliance
- Standards referenced, not reproduced: NACA TR-824 is named for
context only; the Thwaites relation and Michel criterion above are
standard engineering methodology, summary-only per standards-map.yaml.
- compliance: STANDARDS-REF, gated: false.
1---2name: boundary-layer-transition3description: Use when you must predict the laminar-turbulent transition location on a two-dimensional body from its edge-velocity distribution: grow the laminar boundary layer with the Thwaites integral relation to obtain the boundary-layer momentum deficit at each station, build the local Reynolds numbers from the edge velocity and that deficit, evaluate the Michel transition criterion against them, and interpolate the first station where the criterion is crossed to give the transition location. Produces the Reynolds-number history along the body, the Michel criterion margin at each station, and the transition location that gates a natural-transition estimate for an airfoil or body. Trigger: boundary-layer-transition, transition-location, thwaites-integral, michel-criterion, natural-transition, edge-velocity distribution, laminar-turbulent transition, airfoil transition onset.4license: Apache-2.05---67# Boundary Layer Transition (aerodynamics/boundary-layer/boundary-layer-transition)89Use when you must predict where the laminar boundary layer turns10turbulent on a two-dimensional body from its edge-velocity11distribution. This leaf implements the standard integral estimate:12grow the laminar layer with the Thwaites relation to get the momentum13thickness theta at each station, then apply the Michel empirical14criterion on the local Reynolds numbers to locate the natural15transition point. The logic is pure Python, stdlib only, and covers a16clean two-dimensional surface (no roughness, sweep or suction inputs17and no Tollmien-Schlichting wave-growth integration; the Michel18criterion replaces an eN envelope). It pairs with19aerodynamics/boundary-layer/boundary-layer-theory, which owns the20flat-plate thickness and skin-friction correlations on either side of21the transition.2223## Domain quick reference2425- Edge-velocity Reynolds number: Re_x = Ue(x) * x / nu with Ue the26 inviscid edge velocity and nu the kinematic viscosity (SI units27 throughout, m, m/s, m2/s).28- Thwaites integral relation for the laminar momentum thickness:2930 theta(x)^2 = THWAITES_C * nu / Ue(x)^6 * integral_0^x Ue(xi)^5 d(xi)3132 with THWAITES_C = 0.45. The integral is evaluated cumulatively with33 the trapezoid rule over the supplied stations; the segment from the34 leading edge (x = 0) to the first station keeps Ue at its35 first-station value, which makes the constant-velocity flat plate36 exact.37- Momentum-thickness Reynolds number: Re_theta = Ue * theta / nu.38- Michel transition criterion (empirical):3940 Re_theta,tr = MICHEL_A * (1 + MICHEL_B / Re_x) * Re_x**MICHEL_P4142 with MICHEL_A = 1.174, MICHEL_B = 22400.0, MICHEL_P = 0.46.43 Transition onset occurs at the first station where Re_theta reaches44 the threshold; the margin m = Re_theta - threshold crosses zero45 there.46- Flat-plate exact solution (verification helper): with constant Ue the47 Thwaites relation closes to Re_theta = sqrt(0.45) * sqrt(Re_x) =48 0.6708 * sqrt(Re_x), so theta = 0.6708 * sqrt(Re_x) * nu / Ue.49- Natural-transition distance on a smooth flat plate follows from the50 Michel crossing, typically Re_x ~ 1.7e6 at low free-stream51 turbulence, an order of magnitude beyond the textbook 5e5 landmark52 that boundary-layer-theory quotes for the onset of instability.53- NACA TR-824 frames the boundary-layer context; the relations above54 are standard engineering methodology, summary-only.5556## Workflow57581. Assemble the station grid: xs (m) strictly increasing and the edge59 velocities ues (m/s) at each station, equal length, all ue > 0.602. Grow the laminar layer with momentum_thickness_profile(xs, ues,61 nu): returns the Thwaites theta at every station.623. Build the Reynolds history with re_theta_profile(xs, ues,63 theta_list, nu) and the Michel threshold with64 michel_threshold(re_x) at each station.654. Run the one-call sweep transition_location(xs, ues, nu): returns66 theta_list, re_theta_list, criterion_margin_list, x_transition67 (first station where the margin is non-negative, or None), the68 transition_index and interp_x_transition (linear interpolation of69 the margin to zero between the bracketing stations).705. For a quick flat-plate check use flat_plate_transition(nu, ue,71 x_max), the analytic natural-transition distance on a72 constant-velocity plate, or michel_criterion(re_x, re_theta) for a73 single point test.746. Confirm the deterministic checks with the contract test75 scripts/test_boundary_layer_transition.py.7677## Worked example7879Smooth flat plate in low-turbulence flow: nu = 1.46e-5 m2/s, Ue = 3080m/s.8182- Momentum thickness from momentum_thickness_profile over x = 0.25,83 1.0, 2.0 m: theta = 2.3399e-4, 4.6797e-4, 6.6182e-4 m. At x = 1 m84 the value matches the exact flat-plate value 0.6708 * sqrt(2.0548e6) * nu / Ue85 = 4.680e-4 m to six digits, and Re_theta(1 m) = 961.6 equals 0.670886 * sqrt(Re_x) (the trapezoid Thwaites integral is exact for constant87 Ue).88- Michel threshold at x = 1 m: michel_threshold(2.0548e6) = 951.15,89 so the margin there is 961.6 - 951.15 = +10.44. On the coarse grid90 the margins are -38.16 (x = 0.25 m), +10.44 (x = 1.0 m) and +58.6091 (x = 2.0 m): transition_location reports x_transition = 1.0 m92 (station value) with interp_x_transition = 0.8389 m between the93 bracketing stations.94- Exact-solution helper: flat_plate_transition(1.46e-5, 30.0, 2.0)95 returns x_tr = 0.8126 m (inside the 0.6-1.1 m band), i.e.96 Re_x,tr = 1.670e6 with Re_theta at the crossing = 866.8 (inside97 800-1100). The margin is negative just below x_tr and non-negative98 at it, as expected for a first-crossing scan.99100## Verification101102- Confirm momentum_thickness_profile on the three-station flat plate103 is monotonic and matches 0.6708 * sqrt(Re_x) * nu / Ue within 1e-6104 relative at every station.105- Confirm the flat-plate Re_theta identity re_theta_profile(...)106 equals 0.6708 * sqrt(Re_x) within 1e-9 relative.107- Confirm flat_plate_transition(1.46e-5, 30.0, 2.0) lies in 0.6-1.1 m108 and the Re_theta at the crossing lies in 800-1100.109- Confirm ValueError rejection of fewer than two stations,110 unequal-length xs/ues, x below zero or not strictly increasing,111 ue <= 0, nu <= 0, re_x <= 0 and re_theta < 0.112- Confirm determinism: repeated calls on identical inputs return113 identical results.114- Run the contract test offline: python3115 scripts/test_boundary_layer_transition.py (32 tests, deterministic,116 under 20 s).117118## Related leaves119120- aerodynamics/boundary-layer/boundary-layer-theory: the laminar and121 turbulent flat-plate thickness and skin-friction correlations that122 bookend the transition point.123- aerodynamics/airfoil/xfoil-analysis: viscous airfoil analysis that124 can supply the edge-velocity distribution and an independent125 transition estimate for comparison.126- aerodynamics/drag-polars/parasite-drag: uses the laminar versus127 turbulent split downstream of transition for wetted-area drag.128129## Pitfalls130131- Feeding a grid that is not strictly increasing, starts below zero, or132 pairs xs and ues of unequal length: the Thwaites integral is only133 exact for the constant-velocity plate; the module rejects such grids134 with ValueError, so validate the station list before calling.135- Quoting the station value as the transition location: on the coarse136 grid transition_location reports x_transition = 1.0 m while the137 linear interpolation of the margin places the crossing at 0.8389 m;138 use interp_x_transition for the location estimate.139- Confusing the Michel natural-transition distance with the 5e5140 instability-onset landmark: on a smooth flat plate the criterion141 crosses near Re_x ~ 1.7e6, an order of magnitude beyond the142 boundary-layer-theory textbook value for the onset of instability.143- Applying the model to forced or roughness-triggered transition: this144 leaf covers clean two-dimensional natural transition only; the Michel145 criterion replaces an eN envelope and takes no roughness, sweep or146 suction input.147- Treating a never-crossed margin as a zero-length run: when the148 criterion is never met, x_transition is None and the body stays149 laminar over the supplied stations - report that outcome rather than150 forcing a crossing.151- Ignoring the margin sign convention at the first station: the sweep152 returns the first station with non-negative margin, so the bracketing153 stations and the sign flip define the crossing, not the station where154 the margin is largest.155156## Behavior contract (gate 3)157158Run the deterministic contract test (stdlib unittest, offline):159160 python3 scripts/test_boundary_layer_transition.py161162The test covers the Thwaites momentum thickness against the flat-plate163exact solution, the worked-example theta at x = 1 m (4.680e-4 m), the164Michel threshold and criterion logic including the equality boundary,165the transition sweep bounds (x_tr in 0.6-1.1 m, Re_theta in 800-1100)166with the station versus interpolated crossing distinction, the margin167sign flip across the crossing, the never-crossed and first-station-168crossed cases, the exact-solution flat_plate_transition helper and its169bounds, ValueError rejection of every non-physical input in the170validation list, and determinism.171172## Compliance173174- Standards referenced, not reproduced: NACA TR-824 is named for175 context only; the Thwaites relation and Michel criterion above are176 standard engineering methodology, summary-only per standards-map.yaml.177- compliance: STANDARDS-REF, gated: false.