Deriving the browser approximation#

The physical calculation in Chapter 1 and Chapters 3–5 follows viscous air and moving cloth together. That is too expensive for this small browser demonstration. Here we replace parts of it one at a time, explaining what each replacement can and cannot show. The only controls remain incoming horizontal wind speed and direction; the mast and boom do not move.

The implementation is in sail-wind-tunnel/physics.mjs and sail-wind-tunnel/main.mjs in this repository. Its constants below are demonstration choices, not experimentally calibrated sail properties.

Step 2: Replace viscous air with a lifting-surface model#

Now freeze the current cloth shape during each air solve. Assume the sail is infinitely thin, the air keeps constant density, viscosity is neglected, and flow stays attached rather than peeling away from the surface. Unlike Chapter 3, air may slide along the cloth. We keep only the condition that its velocity through the surface is zero, and impose it at selected points rather than everywhere.

A vortex describes circulation of air around a line or region. To define circulation, imagine walking once around a closed loop and adding velocity along the direction of every little step. Let \(\mathbf u\) be air velocity (m/s), \(d\boldsymbol\ell\) a directed tiny step around that loop (m), and \(\Gamma\) the resulting circulation (m²/s). The dot product takes velocity along the step; the closed-loop integral adds all such contributions:

\[\Gamma=\oint\mathbf u\cdot d\boldsymbol\ell.\]

A vortex lattice replaces the lifting surface with a collection of idealized vortex lines. Each panel receives a horseshoe-shaped line: one segment across the sail and two trailing legs extending downstream. The across-sail segment is called bound because it stays on the surface; the trailing legs represent the disturbed air behind it, or wake. Here the segment sits at one quarter of the panel’s width and the point where we enforce zero normal velocity sits at three quarters. The downstream legs are 70 m long.

Index \(j\) identifies a horseshoe. Its unknown strength \(\Gamma_j\) is circulation in m²/s. Let \(\mathbf v_j(\mathbf x)\) be its induced velocity per circulation at position \(\mathbf x\) (m). Thus \(\mathbf v_j\) has units 1/m, and \(\Gamma_j\mathbf v_j\) has units m/s. “Induced” means the change in velocity supplied by that modeled vortex.

Index \(i\) identifies a control point \(\mathbf x_i\) (m), where \(\mathbf n_i\) is the dimensionless unit normal. Recall that \(\mathbf W\) is incoming wind velocity (m/s). The normal component of incoming plus induced velocity must vanish, giving

\[\sum_j\Gamma_j \left[\mathbf v_j(\mathbf x_i)\cdot\mathbf n_i\right] =-\mathbf W\cdot\mathbf n_i.\]

Both sides are in m/s. The right side is the incoming through-surface velocity that the vortices must cancel. For this mesh there are 60 equations and 60 strengths. At fixed geometry, the bracketed coefficients are known: this is a linear system, a set of equations whose unknowns are only multiplied by known coefficients and added together.

The circulation field and surface-flow condition follow the method described in Drela’s JVL formulation, Sections 4.2 and 5.2–5.3. Our sail demonstration is a much simpler implementation, not JVL itself. The computer solves its coefficient table using elimination, choosing large available coefficients as divisors to avoid dividing by nearly zero values. That is what a pivoted solve means.

The induced field uses the Biot–Savart relation: an ideal vortex segment’s strength and geometry determine its velocity contribution. Section 4.2 and Appendix 9.1 of Drela’s JVL formulation give that relation and its horseshoe evaluation. The demo softens the near-line velocity over a 0.035 m core radius to avoid an infinite value on the ideal line. This is a numerical modification, not a resolved physical vortex core.

Straight trailing legs supply a conventional lifting-surface approximation to smooth flow leaving the rear edge. This demo does not independently solve the viscous trailing-edge behavior. It also does not let the wake curve up, retain previously shed vortices, or resolve separation. Finite sail height does allow three-dimensional induced velocity above the head, but that alone does not establish real separated flow spilling over the top.

Step 3: Turn circulation into approximate forces#

For one panel, let \(\mathbf F_v\) be vortex-derived force (N), \(\rho=1.225\) kg/m³ the chosen air density, and \(\Gamma\) that panel’s circulation (m²/s). Let \(\mathbf v_w\) be velocity from all trailing wake legs at the bound segment’s midpoint (m/s), and \(\Delta\boldsymbol\ell\) the directed bound segment (m). The delta here means a finite segment, not a derivative.

The cross product \(\times\) produces a vector perpendicular to its two input vectors. Its magnitude is the product of their lengths times the sine of their angle, with direction fixed by the right-hand rule. The demo applies a discrete Kutta–Joukowski force:

\[\mathbf F_v =\rho\Gamma(\mathbf W+\mathbf v_w)\times\Delta\boldsymbol\ell.\]

The vector force relation is described in Drela’s JVL formulation, Section 6.1, equation (108). Using only wake-induced velocity in this evaluation is a demo simplification; bound-segment contributions are omitted. Its units give a useful check:

\[\frac{\text{kg}}{\text{m}^3} \frac{\text{m}^2}{\text{s}} \frac{\text{m}}{\text{s}}\text{m} =\frac{\text{kg m}}{\text{s}^2}=\text{N}.\]

For a teaching example, circulation 1 m²/s, perpendicular speed 6 m/s, and segment length 0.20 m give force magnitude 1.47 N at this density. This is an integrated load approximation, not the two viscous face tractions from Chapter 4.

The demo adds a second, empirical force along the incoming wind. Let \(\mathbf F_f\) be that force (N), \(U\) wind speed (m/s), \(A\) current panel area (m²), and \(\mathbf e=\mathbf W/U\) the dimensionless wind direction for nonzero speed. Choose dimensionless coefficient \(C_f=0.008\). Then

\[\mathbf F_f=\frac12\rho U^2 A C_f\mathbf e.\]

This uses the force scaling of NASA’s drag equation. The coefficient and the choice of current sail area are our assumptions, not a measured cloth-friction law. No viscous stress is actually solved. For \(U=6\) m/s and \(A=0.10\) m² this term is about 0.0176 N. At zero wind speed the implementation applies zero wind load, rather than dividing by zero to find a direction.

Each panel’s combined load is shared equally among its four corners, including pinned corners. This preserves total applied force; it does not guarantee exact turning effect, or moment, about every possible point.

For coloring, let \(p_{\text{load}}\) be the signed average normal-load proxy (Pa) and \(\mathbf n\) the panel’s dimensionless unit normal. The normal follows a consistent side of the material, not whichever way the wind happens to blow:

\[p_{\text{load}}=\frac{\mathbf F_v\cdot\mathbf n}{A}.\]

This is normal force divided by area, not separately measured pressure on both faces. Changing a coloring convention must never change the actual force.

Step 4: Alternate air solves and cloth updates#

The cloth takes four steps of 1/240 s between air solves, giving a nominal 60 Hz refresh in simulated time. Hz means refreshes per second. The new shape changes the next vortex lattice and hence the next load. However, each air solve still treats the surface as stationary. It omits acceleration of surrounding air by moving cloth, called added mass in Chapter 5, and changes in the wake’s history. This is quasi-steady feedback: a succession of frozen-shape flow solves, not the converged moving-surface calculation.

Smoke dots are passive tracers, points moved by the computed velocity without pushing back on it. Let \(\mathbf q\) be one tracer’s position (m) and \(t\) simulated time (s). Its derivative is its velocity. Using the same horseshoes and strengths as above, the implemented rule is

\[\frac{d\mathbf q}{dt} =\mathbf W+\sum_j\Gamma_j\mathbf v_j(\mathbf q).\]

The midpoint update first estimates a half-step position, samples velocity there, and uses that velocity for the full step. This is the second-order Runge–Kutta method, commonly shortened to RK2; it improves on using only velocity at the step’s starting position for a sufficiently smooth field. MIT’s numerical-modeling notes, Section 7.1, equation (7.9), derive this midpoint rule.

A dot’s recorded history is a pathline, the path one particle has taken. A streamline instead follows velocity directions throughout one instantaneous snapshot. They need not agree while the sail changes shape. The plotted histories are pathlines. Smoke has no volume, buoyancy, diffusion, or influence on air motion in this model. Zero through-surface velocity at isolated control points does not guarantee the same between them: a tracer crossing the coarse sail is not evidence of physical fabric permeability.

Calculation flaws and the useful range#

Incidence is the angle between incoming wind and the sail’s nominal surface direction. Modest forward incidence, roughly within ±20 degrees, is the intended qualitative range, not an experimentally established limit for attached flow. A bent panel may still have a much larger local angle. The interactive demo withholds predictions outside its chosen forward range; that means “unsupported,” not a physical zero force.

A diagnostic can deliberately bypass this guard to inspect the raw method. For a frozen manufactured cut at 6 m/s, changing direction from 89.9 to 90.1 degrees changed the largest foot-panel force from about 1239 N to 123 N. The algorithm switches which edge it treats as the front when the wind’s boom-axis component changes sign. That changes bound-segment and control-point locations, not merely colors. A small equation residual did not prevent a large, physically unsupported result. Smoothing the jump would hide the missing separation physics rather than supply it.

Other omitted effects include irregular turbulent air motion, vortices formed by separated front-edge flow, blockage by the mast and boom, the ground’s influence on air motion, cloth touching itself or the rig, and measured fabric behavior. Stable numbers and attractive smoke paths do not validate these missing mechanisms.