FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Tags · OpenSourceAWE/VortexStepMethod.jl · GitHub

Tags: OpenSourceAWE/VortexStepMethod.jl

Tags

v4.2.0

Toggle v4.2.0's commit message
[Diff since v4.1.2](v4.1.2...v4.2.0)

- Shared panel aerodynamics (`src/panel_aerodynamics.jl`): the per-panel physics
  written once as pure, branch-free, number-type-generic functions of the section
  geometry and the flow — `panel_axes`, `panel_inflow`, `panel_force_directions`,
  `panel_loads` and the small helpers around them. `update_panel_properties!`,
  `init_pos!`, `calc_forces!` and `calculate_results` now call them instead of
  spelling the algebra out three times, and `SymbolicAWEModels` traces the same
  functions with symbolic arguments to build its equations, so the two packages
  can no longer drift apart. Panel geometry is unchanged bit for bit; forces,
  moments and coefficients agree to within 1 ulp, the products having been
  reassociated. `calc_forces!` stays zero-allocation.
- `effective_alpha` and the `deficiency` argument of `panel_inflow` carry an
  unsteady lag (a Wagner indicial deficiency) into the angle the polars are read
  at, while the geometric angle still turns the force. Unused by the solver,
  which has no unsteady state; it is shared so a symbolic consumer that does have
  one reads the same definition.

- `section_pitch_rate` gained a three-argument form taking the trailing minus
  leading edge apparent wind directly. The four-argument form is unchanged.
- Norms inside the shared panel aerodynamics are floored (`smooth_norm`) rather
  than guarded by branches, so the expressions are differentiable and traceable.
  The floor is `1e-12` m, which moves no reported quantity.

**Merged pull requests:**
- Write the panel aerodynamics once, as traceable functions (#265) (@1-Bart-1)

v4.1.2

Toggle v4.1.2's commit message
[Diff since v4.1.1](v4.1.1...v4.1.2)

- Billowing now takes its rotation axis from the section pair itself instead of
  projecting the leading-edge span vector on `spanwise_direction`. Sections run
  `+y` to `-y`, so the pair already fixes the sign. The projection was decided by
  3 % of the vector on a C-shaped kite's tip panels — 11 mm of span between the
  outermost sections — so a deforming tip could flip that one panel's billow.

**Merged pull requests:**
- Take the billow axis from the section pair, not a global projection (#264) (@1-Bart-1)

v4.1.1

Toggle v4.1.1's commit message
[Diff since v4.1.0](v4.1.0...v4.1.1)

- Section twist now rotates the chord fully about the spanwise axis. The axial
  Rodrigues term was missing, so a swept or dihedral section's along-span chord
  component was scaled by `cos(theta)`: the chord shortened and tilted out of the
  twist plane, growing as `theta^2`.

**Merged pull requests:**
- Rotate a twisted section's chord fully about the spanwise axis (#263) (@1-Bart-1)

v4.1.0

Toggle v4.1.0's commit message
[Diff since v4.0.0](v4.0.0...v4.1.0)

- `table_format` keyword on `write_section_aero`, `generate_airfoils`, `obj_to_yaml`
  and `surfplan_to_aero_yaml`: `:csv` (default, readable) or `:arrow` (binary, ~40×
  faster to load and 2.6× smaller). `read_section_aero` detects the format from the
  file suffix, so a geometry YAML can reference either.
- `geometry_path` keyword on `obj_to_yaml`, naming the geometry YAML itself
  instead of always writing `output_dir/geometry.yaml`. Point it outside the
  table directory and the emitted table references carry the path from the YAML's
  directory to `output_dir`, which is what the geometry loader resolves them
  against — so a generated dataset can keep its bulk in a subdirectory while the
  geometry sits with the hand-written ones.
- `convert_node_table` and `write_node_rows` rewrite a per-node table in the format
  the destination suffix names. `obj_to_yaml` migrates an existing dataset with
  them when `table_format` differs from what the directory holds, so a dataset
  changes format without re-running the airfoil solver that produced it.
- `flow_curvature` solver setting (default `false`). When enabled, each section
  gets the thin-airfoil pitch-rate moment increment `Δcm = -(π/4) q̂` with
  `q̂ = q c / (2 v_rel)`. A section rotating about its own spanwise axis sees an
  incidence that varies linearly along the chord, which is equivalent to
  parabolic camber and produces a quarter-chord moment that a single control
  point cannot represent. The lift response to `q` was already exact because the
  inflow is sampled at the three-quarter-chord point, so only the moment was
  missing.
- `pitch_rate_dist` field on `BodyAerodynamics`, holding the `q` above per panel.
  `set_va!(body_aero, va, omega)` fills it by projecting `omega` onto every
  panel's `y_airf`, so panels at different dihedral see different rates from one
  body rate. The distributed `set_va!(body_aero, va_distribution;
  pitch_rate_dist)` takes it directly, so twist and flapping rates of a deforming
  wing — which no single body rate can express — reach the moment. Omitting the
  keyword zeroes it rather than reusing a stale `omega`, which the distributed
  form never sets.
- `section_pitch_rate(velocity_leading, velocity_trailing, z_airf, chord)` builds
  one entry of that distribution from a section's edge velocities, and reduces to
  `ω ⋅ y_airf` for rigid motion.
- `bin/update_default_manifests` regenerates both checked-in default manifests in
  one command, and `bin/install` takes `+X.Y` / `--version X.Y` to pick a Julia
  channel without prompting. Selecting a version no longer moves the juliaup
  default, so regenerating the 1.11 manifest leaves the shell on whatever channel
  it was using.

- The `Solver` docstring quoted the `SolverSettings` defaults for
  `type_initial_gamma_distribution` and `core_radius_fraction` (`ELLIPTIC`, `1e-20`)
  instead of its own (`ZEROS`, `0.05`), and never said what `core_radius_fraction`
  measures. It now documents the `Solver` defaults and cites Damiani et al. (2019) for
  the 0.05 cut-off.
- A remesh under `use_prior_polar` no longer resamples the refined sections'
  `SectionAero` surface tables down to whatever unrefined sections survive it.
  `compute_refined_section_interpolation!` reblended contour, `cp` and `cf` from the
  unrefined sections unconditionally while `aero_data` was preserved, so a wing rebuilt
  onto fewer structural stations kept full-resolution polars but lost the surface tables
  pressure integration reads. The reblend is now skipped when the polars are preserved
  and the refined sections already carry tables.
- The angle-of-attack correction (`correct_aoa=true`) no longer overwrites
  `body_aero.AIC` with the aerodynamic-centre (LLT) matrix. It builds that matrix in
  its own `AIC_aero_center` field, so `AIC` keeps holding the control-point matrix the
  circulation was solved against, which is what anything reading it after a solve
  expects. Costs a second `n_panels × n_panels × 3` buffer.
- `obj_to_yaml` no longer places sections on a wingtip that has closed to a point.
  `station_indices` spreads its targets over the stations that still have a chord,
  so the outermost section lands on the last sliceable one. A V3 mesh sliced with
  the default `wingtip_distance` used to put a zero-chord section at each tip,
  whose polar was `NaN` and took the whole solve with it; working around it meant
  guessing a `wingtip_distance` large enough to skip past the tip. That workaround
  is no longer the default: `wingtip_distance` is now `0.0`, an inset on top of the
  trim for meshes whose slices just short of the tip are still too thin to analyse.
- Wing sections are normalized to `+y` to `-y` order on load (`normalize_span_order!`),
  and by `refine!` for wings built through `add_section!`. Panel `y_airf` and `z_airf`
  follow the order sections are stored in, so a geometry file written the other way
  round inverted every panel normal, and a wing whose sections were replaced after its
  panels were built (a structural remesh) inverted them mid-run, one panel at a time as
  each crossed `spanwise_direction`. `obj_to_yaml` and `surfplan_to_aero_yaml` emit that
  order too; files of either order keep loading the same.
- Spanwise distribution plots put `+y` on the left, matching that order and the kite
  seen from the front.
- The lofted airfoil skin in `plot_geometry` draws each section's contour on its own
  panel edge (#256). The edge was picked from the wing's span order rather than from
  the panel index, so a wing whose sections ran `-y` to `+y` got every rib drawn at its
  neighbour's station, one tip bare and the other doubled, while the panels themselves
  rendered correctly.

- `SolverSettings` now defaults to the same values as `Solver`: `core_radius_fraction`
  `1e-20` → `0.05` and `type_initial_gamma_distribution` `ELLIPTIC` → `ZEROS`. The 0.05
  bound vortex core cut-off follows Damiani et al. (2019), "A Vortex Step Method for
  Nonlinear Airfoil Polar Data as Implemented in KiteAeroDyn", and matches the upstream
  `awegroup/Vortex-Step-Method` default; at `1e-20` the Biot-Savart singularity guard
  never engaged. Coefficients are unchanged for well-separated geometry, since the guard
  only triggers where a control point falls within 5% of a filament length of a bound
  vortex, and every settings file shipped in `data/` sets both keys explicitly.
- `BodyAerodynamics.AIC` is stored as `(n_panels, n_panels, 3)` instead of
  `(3, n_panels, n_panels)`, so each component slice `AIC[:, :, k]` is contiguous and
  the induced-velocity products reach BLAS `gemv` instead of the generic fallback.
  `solve!` is 3.1–5.3× faster (n=120, VSM: 26.1 ms → 4.9 ms inviscid, 21.1 ms →
  6.0 ms with polars). Code reading `AIC[k, i, j]` must become `AIC[i, j, k]`.
- The filament induced-velocity kernels reuse the `r0`/`length` each `BoundFilament`
  already stores, take the core-radius cutoff from `|r1.r0|/|r0|` without forming the
  perpendicular vector, and defer the cross products that only one branch reads. Output
  is bit-identical; `solve!` is a further 1.47-1.55x faster.
- `read_node_table` parses into a preallocated matrix instead of `reduce(vcat, …)`
  over a generator, which was quadratic in the row count: ~21× faster on a 16 MB
  surface table (2.49 s → 0.12 s), benefiting every existing dataset.
- `is_show=true` draws into a window named after the plot title instead of into
  whichever window the backend last used, so a script showing several plots gets
  one window each and re-running it redraws them in place. `show_plot` takes the
  window `name` as a keyword.
- `examples/V3_kite.jl` builds its wing from `VSMSettings` and adds a second sweep on
  polars generated from `V3_25.obj` with NeuralFoil (`NEURALFOIL`, on by default), so
  the plots compare CAD-derived polars against the checked-in CFD tables.
- `bin/run_julia` starts Julia with `JULIA_NUM_THREADS=auto` unless the environment
  already sets it.

**Merged pull requests:**
- Fix lofted-airfoil rib placement for +spanwise section order (#256) (@1-Bart-1)
- Faster node tables (#257) (@1-Bart-1)
- Normalize wing section order to +y → -y (#258) (@1-Bart-1)
- Faster solve!: BLAS-friendly AIC layout + leaner filament kernels (5.4-8.0x) (#259) (@1-Bart-1)
- Optional flow-curvature pitch-rate moment (#260) (@1-Bart-1)

v4.0.0

Toggle v4.0.0's commit message
[Diff since v3.3.6](v3.3.6...v4.0.0)

- `NeuralFoil`-based airfoil polar generation via the new `AirfoilAero` submodule
  (`NeuralFoilSolver`, `XFoilSolver`, `analyze_section`, `analyze_sweep`,
  `fit_kulfan_parameters`, `shrink_wrap`, `ShrinkWrap`)
- `ObjAdapter` submodule: converts a 3D wing `.obj` mesh to the native YAML/CSV
  geometry format (`obj_to_yaml`, `perpendicular_sections`,
  `write_yaml`, `plot_slices_3d`, `plot_airfoils`)
- `SurfplanAdapter` submodule: `surfplan_to_aero_yaml` turns a SurfplanAdapter aero
  export into the native pressure-ready YAML/CSV geometry (shared `generate_airfoils`
  core with `ObjAdapter`)
- `ObjWing(obj_path[, dat_path]; Re, n_panels, aero_solver, remake, ...)` convenience
  constructor restored for backward compatibility — internally calls
  `ObjAdapter.obj_to_yaml` then `Wing`; `aero_solver` selects the polar backend
  (default `NeuralFoilSolver()`; pass `XFoilSolver()` for old behavior);
  `remake=false` (default) reuses an existing `geometry.yaml` in `output_dir` to skip
  expensive polar generation when only `n_panels` changes; set `remake=true` to force
  regeneration
- Per-section surface aero tables: `SectionAero` (full contour + surface pressure
  `cp` + skin friction `cf` per node over an `(α, δ)` grid), `section_surface`,
  `read_section_aero` / `write_section_aero`; surface aero propagates through
  `Section` and `Wing` and is spanwise-interpolated during `refine!`
- `POLY` aero model for polynomial cl/cd/cm (exported)
- `lei_poly_coeffs(tube_diameter, camber)` (exported from `AirfoilAero`) returning
  the Breukels α-polynomial cl/cd/cm coefficients
- Li/Gaunaa spanwise artificial viscosity (Li, Gaunaa, Pirrung & Lønbæk,
  TORQUE 2026) for the LOOP solver, stabilizing post-stall circulation
  distributions that otherwise develop non-physical sawtooth oscillations;
  opt-in via `is_with_artificial_viscosity` (default `false`) and
  `artificial_viscosity_factor` (default `0.035`) on the solver settings
- `crease_frac` wing setting (chordwise flap-hinge fraction, default `0.75`)
  for drawing the δ-deflected plate/skin, readable from YAML
- `examples/V3_neuralfoil.jl` and `examples/obj_to_yaml_kite.jl`

- BREAKING - `ObjWing` polar generation now uses NeuralFoil (via
  `ObjAdapter.obj_to_yaml`) instead of XFoil + a user-supplied `.dat` file. The
  constructor signature is backward-compatible (`dat_path` is accepted and
  silently ignored), but the resulting aerodynamic polars will differ
  numerically from v3.x outputs. To reproduce old XFoil-based polars pass
  `aero_solver=XFoilSolver()` to `ObjAdapter.obj_to_yaml` and call `Wing`
  directly.
- OBJ-based wings are now built via `ObjAdapter.obj_to_yaml` + `Wing(yaml_path)`
  instead of the old `ObjWing` pipeline (XFoil + single `.dat` file);
  `ObjWing` is kept as a shim that accepts but ignores `dat_path`
- BREAKING - `LEI_AIRFOIL_BREUKELS` is now a deprecated alias of `POLY`, and the
  built-in Breukels regression no longer runs at solve time. Sections must carry
  the α-polynomial coefficients directly instead of `(tube_diameter, camber)`;
  compute them up front with `lei_poly_coeffs(tube_diameter, camber)`
- `Section` and `add_section!` accept an optional `section_aero` argument
- BREAKING - plotting is now Makie-only; the `VortexStepMethodMakieExt` extension
  loads once a Makie backend and
  [`MakieControlPlots`](https://github.com/OpenSourceAWE/MakieControlPlots.jl) are
  available, so plotting code must now load `MakieControlPlots` (and drop
  `set_plot_backend!`); `plot_section_polars` is rendered through `MakieControlPlots`

- `ObjWing` as a standalone pipeline (replaced by `ObjAdapter`); the name is
  re-exported as a compatibility wrapper
- `auto_rotation` helper (internal, removed from public API)
- `PanelGroupingMethod` enum (already removed in v3.0.0 — stale docs entry cleaned up)
- ControlPlots test run removed from CI (`plot-controlplots` arg) due to
  a `libraqm`/HarfBuzz symbol conflict in the GitHub Actions environment
- BREAKING - the `ControlPlots` plotting extension, `examples_cp/`, and the
  `PythonCall`/Matplotlib setup (`bin/install_controlplots`, CondaPkg
  `LocalPreferences` defaults)
- BREAKING - the `PlotBackend`/`MakieBackend`/`ControlPlotsBackend` types and
  `set_plot_backend!`; plotting works as soon as a Makie backend and
  `MakieControlPlots` are loaded
- the never-implemented `plot_circulation_distribution`

**Merged pull requests:**
- CompatHelper: bump compat for Parameters to 0.13, (keep existing compat) (#243) (@github-actions[bot])
- Add Li/Gaunaa spanwise artificial viscosity for post-stall stabilization (#247) (@1-Bart-1)
- Add neuralfoil and automatic conversion from obj to yaml (#249) (@1-Bart-1)
- Bump codecov/codecov-action from 6 to 7 (#250) (@dependabot[bot])
- Bump actions/cache from 5 to 6 (#251) (@dependabot[bot])
- Bump actions/checkout from 6 to 7 (#252) (@dependabot[bot])
- Remove ControlPlots; migrate plotting to Makie + MakieControlPlots (#253) (@1-Bart-1)
- Route crease_frac, fix 1.12.6 docs build, add manifest --update tooling (#254) (@1-Bart-1)
- Aero gen (#255) (@1-Bart-1)

**Closed issues:**
- Use NeuralFoil instead of Xfoil (#105)
- The sqrt in elliptical distribution throws a domainerror sometimes (#144)
- Reimplementcurrent polar plotting scripts with Makie scripts (#202)

v3.3.6

Toggle v3.3.6's commit message
[Diff since v3.3.5](v3.3.5...v3.3.6)

- `calc_forces!` and `solve_base!` (both exported): `solve!` is now
  `solve_base!` followed by `calc_forces!`, so a frozen circulation can be
  mapped to forces without re-running the nonlinear gamma solve (#245)
- `calculate_cd` and `calculate_cm`, splitting the combined `calculate_cd_cm`
  into separate drag- and moment-coefficient functions; `calculate_cd_cm` is
  kept as a thin wrapper (#246)

- `calc_forces!` is now allocation-free in the per-step hot path
  (preallocated `panel_area_dist` and `unrefined_count_dist` buffers) (#245)

- 3D polar plotting (#245)
- flaky Aqua `persistent_tasks` test now actually disabled via
  `persistent_tasks=false` (`()` did not disable it) (#246)

**Merged pull requests:**
- Split calc_forces! out of solve! and make it zero-alloc (#245) (@1-Bart-1)
- Split cd and cm (#246) (@1-Bart-1)

v3.3.5

Toggle v3.3.5's commit message
[Diff since v3.3.4](v3.3.4...v3.3.5)

- `moment_coeff_unrefined_dist` field in `VSMSolution`: the summed
  `moment_frac`-referenced pitching-moment coefficient per unrefined section [-]

**Merged pull requests:**
- Add dist (#244) (@1-Bart-1)

v3.3.4

Toggle v3.3.4's commit message
[Diff since v3.3.3](v3.3.3...v3.3.4)

- `PlotBackend`, `MakieBackend`, `ControlPlotsBackend`, and
  `set_plot_backend!` so applications can explicitly choose which plotting
  extension the backend-agnostic plotting API should use
- `PythonCall` added as a weak dependency to support the `ControlPlots`
  backend with PythonPlot

- backend-agnostic plotting wrappers now route through the active plotting
  backend, and each plotting extension initializes itself as the default only
  when no backend has been selected yet
- relaxed `ControlPlots` compatibility to include both `0.2.5` and `0.3`
- improved `bin/install` and `bin/install_controlplots` scripts

- corrected projection onto core radius in `velocity_3D_bound_vortex!` and
  semi-infinite trailing vortex projection so that the radial direction is
  always measured from the filament axis, not from the origin (#241)
- fixed 0-based subplot indexing in `ControlPlotsExt` for PythonPlot
  compatibility (`plot_distribution` no longer errors with PythonPlot backend)
- fixed missing initialization of `damp` in `solver.jl`

**Merged pull requests:**
- Fix branch 3 direction (#241) (@1-Bart-1)
- Allow ControlPlots 0.3 (#242) (@ufechner7)

v3.3.3

Toggle v3.3.3's commit message
[Diff since v3.3.2](v3.3.2...v3.3.3)

- `MakieExt` and `ControlPlotsExt` no longer both define
  `VortexStepMethod.plot_geometry` for the same type, resolving a method
  ambiguity when both extensions were loaded (#236)
- `menu()` and `menu_cp()` now always set the active backend before dispatching
  to a plot function, preventing stale-backend errors

**Merged pull requests:**
- Fix MakieExt and ControlPlotsExt define VortexStepMethod.plot_geometry for the same type (#237) (@ufechner7)

**Closed issues:**
- MakieExt and ControlPlotsExt define VortexStepMethod.plot_geometry for the same type (#236)

v3.3.2

Toggle v3.3.2's commit message
[Diff since v3.3.1](v3.3.1...v3.3.2)

- use 2-arg version of atan to avoid possible NaN

Back | FazBrowse Home | New Git URL