Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
686636e
AWAE: add missing description of some variables and routines.
andrew-platt May 12, 2026
2ec4f49
AWAE: write wake-plane wireframes to VTK output
andrew-platt May 13, 2026
0eb4bbf
FF: update plan to rev26
andrew-platt May 13, 2026
ec7299e
AWAE: add vtk outputs for each plane. First cut
andrew-platt May 13, 2026
f9694ed
AWAE: add a .vtk.series file for wireframe outputs
andrew-platt May 13, 2026
5c0f840
AWAE: change name for vtkroot, add wake vtk root
andrew-platt May 14, 2026
ddade81
WD: edges of wake planes were not updated in cartesian/curled
andrew-platt May 20, 2026
6a8721e
AWAE/WD: unitinitialized allocatable arrays
andrew-platt May 21, 2026
cf96c93
WD: init values for cartesian/curl planes 0+1
andrew-platt May 21, 2026
d6198e0
FF: update MaxPlanes calculation for cartesian/curl
andrew-platt May 21, 2026
f5ab30a
AWAE: wake plane vtk output missing z contibution
andrew-platt May 21, 2026
0a0fefe
AWAE: move wake visualization into subdirectory
andrew-platt May 21, 2026
a7c102c
FF: change calculations for MaxNumPlanes
andrew-platt May 26, 2026
450056b
docs: add docs for FAST.Farm wake extent
andrew-platt May 26, 2026
791baa8
WD: fix smooth tapering from `numDFull` to `numDBuff` for curled wake
rthedin May 29, 2026
525238e
AWAE: add flag placeholder for when to write planes
andrew-platt Jun 8, 2026
cc3d13b
Merge pull request #32 from rthedin/bugfix/taperfix
andrew-platt Jun 8, 2026
2b6292a
AWAE: extract VTK wake-plane output into new AWAE_vtk module
andrew-platt Jun 10, 2026
c285f45
AWAE: add Write_WireFrame_Series for per-turbine wireframe .vtk.serie…
andrew-platt Jun 11, 2026
d78d541
AWAE: add .vtk.series writer for disturbed-wind slices
andrew-platt Jun 11, 2026
155d40d
Fix missing Vx_wake2 initialization at T=0 for Curl/Cartesian wake mo…
andrew-platt Jun 18, 2026
c192db7
Update .gitignore for VScode + docker configs
andrew-platt Jun 19, 2026
c898551
WD: error handling fix from GH copilot
andrew-platt Jun 19, 2026
13536ed
AWAE: put GridTol back in
andrew-platt Jun 19, 2026
2d2320f
Update TSinflow_curl results after correcting decay
andrew-platt Jun 23, 2026
9601550
AWAE: make planeDomainExit 3D and handle each dimension independently
andrew-platt Jul 1, 2026
19d514a
AWAE/WD: pass wake plane domain-exit flags to WakeDynamics for OOB me…
andrew-platt Jul 2, 2026
0755f49
WD: minor code cleanup, swap order plane merging checks
andrew-platt Jul 2, 2026
8056096
Fix amrex_reader_utest to compile in both single and double precision
andrew-platt Jul 7, 2026
db047db
WakeDynamics: drop individual buffer-exit planes with shift instead o…
andrew-platt Jul 9, 2026
fb80e5e
Replace wakePlaneDomainExit with LowResBounds parameter in WakeDynamics
andrew-platt Jul 9, 2026
12af71a
FAST.Farm: foundation for terrain-following and axis-aligned planar o…
andrew-platt Jul 16, 2026
eff99bc
FAST.Farm: Feature - axis-aligned planar sampling (NumPlaneSlices)
andrew-platt Jul 17, 2026
e7ace15
FAST.Farm: Feature - terrain-following point-cloud sampling (NumTerra…
andrew-platt Jul 17, 2026
cdfb610
FAST.Farm docs: document the new NumPlaneSlices / NumTerrainSlices bl…
andrew-platt Jul 17, 2026
1218c9f
FAST.Farm: resolve variable shadowing warning diagnostics
andrew-platt Jul 17, 2026
c7d4c9e
FAST.Farm: change WrPlaneDT/WrTerrainDT DEFAULT fallback to DT_Low
andrew-platt Jul 21, 2026
24cab69
FAST.Farm: NumPlaneSlices 'normal' column → 'plane' keyword (XY/YZ/XZ)
andrew-platt Jul 21, 2026
c349540
FAST.Farm: make PlaneSlices and TerrainSlices input sections required
andrew-platt Jul 21, 2026
83d70d9
FAST.Farm: address Copilot review findings (6 fixes)
andrew-platt Jul 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,8 @@ varcache
# Python cache files
openfast_io/dist/
openfast_io/openfast_io/_version.py

# docker with VScode config
*.code-workspace
docker-compose.yml
.devcontainer/
Binary file not shown.
Binary file not shown.
Binary file removed docs/OtherSupporting/FAST.Farm_Plan_Rev25.doc
Binary file not shown.
25 changes: 25 additions & 0 deletions docs/source/user/api_change.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,31 @@ The changes are tabulated according to the module input file, line number, and f
The line number corresponds to the resulting line number after all changes are implemented.
Thus, be sure to implement each in order so that subsequent line numbers are correct.

OpenFAST v5.0.x to next release
-------------------------------

Two new optional VISUALIZATION sub-sections were added to the FAST.Farm
primary input file to give users finer control over what gets written
as VTK output. Legacy decks that do not include either block continue
to work unchanged.

The first block, ``--- AXIS-ALIGNED PLANE SLICES (extent-controlled) ---``,
lets the user specify axis-aligned uniform-grid slices with explicit
2-D extents anywhere in the low-resolution domain (Feature 2, plan
§3). Output is XML VTK ``.vts`` + ``.vts.series``. The block header
is optional and, when present, sits between the existing VISUALIZATION
block and the OUTPUT block.

The second block, ``--- TERRAIN-FOLLOWING SAMPLING ---``, lets the user
emit point clouds sampled from STL surfaces or plain-text/CSV files,
lifted to one or more offset sheets along either an explicit normal
or the STL per-facet normal (Feature 3, plan §2). Output is XML VTK
``.vtp`` + ``.vtp.series``.

See :numref:`FF:Input:PlaneSlices` and :numref:`FF:Input:TerrainSlices`
for the full grammar, and :numref:`FF:sec:SliceOutputs` for guidance
on which slice path to pick.

OpenFAST v4.2.x to OpenFAST v5.0.0
-----------------------------------

Expand Down
9 changes: 9 additions & 0 deletions docs/source/user/fast.farm/FutureWork.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,12 @@ releases:
- Adopt the capability to support undersea marine turbine arrays (which
may require supporting direct feedthrough of input to output to
handle the added-mass effects).

- Extend the terrain-following sampling
(:numref:`FF:Input:TerrainSlices`) to also accept arbitrary
non-axis-aligned planar samples. Today the extent-controlled plane
slice feature (:numref:`FF:Input:PlaneSlices`) only accepts the
keywords ``XY``, ``YZ``, and ``XZ`` with a
fatal init error for any other value. See GitHub
issue `#2383 <https://github.com/OpenFAST/openfast/issues/2383>`__
for the motivating discussion and one proposed grammar.
176 changes: 176 additions & 0 deletions docs/source/user/fast.farm/InputFiles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,182 @@ Therefore, disabling visualization is recommended when running many
FAST.Farm simulations. See :numref:`FF:Output:Vis` for
visualization output file details.

.. _FF:Input:PlaneSlices:

Axis-Aligned Plane Slices (extent-controlled)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This optional block lets the user emit an arbitrary number of
axis-aligned uniform-grid VTK slices, each with a user-controlled 2D
extent placed anywhere in the low-resolution domain. Unlike the classic
**NOutDisWindXY** / **YZ** / **XZ** slices above (which always span the
entire low-res domain), each slice here is bounded by an explicit
2-D extent, so a single hub-height cut through a large farm can be
kept to just the region of interest.

The block is optional. Legacy decks omit it entirely; older files still
parse without modification.

The block begins with the section header
``--- AXIS-ALIGNED PLANE SLICES (extent-controlled) ---`` and is
followed by:

- **NumPlaneSlices** [integer] specifies the number of
extent-controlled axis-aligned planar slices to output
(:math:`0` to :math:`99`). Set to :math:`0` to disable the feature.

- **WrPlaneDT** [sec] specifies the sampling period for this
feature. **DEFAULT** falls back to **DT_Low**. Internally rounded
to the nearest multiple of **DT_Low**. Independent of the classic
**WrDisDT** so that (for example) a small hub-height sheet can be
sampled frequently while heavier full-domain outputs sample rarely.

- A two-line column header followed by **NumPlaneSlices** slice rows
with the following columns:

**SliceName** — quoted string. Free-form slice name; appears in the
output file names. Example: ``"T1_0D"``.

**origin(m)** — 3-vector, in metres. Plane corner (not centre)
in the farm-global frame. Example: ``(0 -300 0)``.

**plane** — keyword. One of ``XY``, ``YZ``, or ``XZ``
(case-insensitive). Specifies the orientation of the sampling
plane. Any other value is a fatal init error.

**extent1(m)** — positive scalar, in metres. In-plane extent
along the first axis of the named plane. Example: ``600``.

**extent2(m)** — positive scalar, in metres. In-plane extent
along the second axis of the named plane. Example: ``400``.

The (extent1, extent2) axes are ordered by the named plane:
``XY`` :math:`\Rightarrow` (X, Y),
``YZ`` :math:`\Rightarrow` (Y, Z),
``XZ`` :math:`\Rightarrow` (X, Z).

Grid resolution is fixed to the low-resolution spacing
(``dX_Low``, ``dY_Low``, ``dZ_Low``); no ``npoints`` column is
required. Both parenthesised and bare numeric vectors parse — the
parser strips ``(``, ``)``, and ``,`` before tokenising.

Output is written as VTK XML ``StructuredGrid`` (``.vts``) plus a
matching ParaView ``.vts.series`` sidecar so time-series playback
works out of the box. Any node whose global-frame position falls
outside the low-resolution domain is written as IEEE quiet NaN;
ParaView automatically masks these.

Example row (three slices — one XY at hub height, one YZ through a
turbine, one XZ through the farm centre):

.. code-block:: none

--- AXIS-ALIGNED PLANE SLICES (extent-controlled) ---
3 NumPlaneSlices - Number of axis-aligned planar slices (-)
DEFAULT WrPlaneDT - Sampling period (s) or DEFAULT (=DT_Low)
SliceName origin(m) plane extent1(m) extent2(m)
(-) (m,m,m) (-) (m) (m)
"hubXY" (700 700 95) XY 1200 600
"crossYZ" (1000 700 5) YZ 600 300
"crossXZ" (700 1000 5) XZ 1200 300

Output naming follows the pattern
``<RootName>.Plane.<SliceName>.<n>.vts`` with a companion
``<RootName>.Plane.<SliceName>.vts.series``, all under ``vtk_ff/``.

.. _FF:Input:TerrainSlices:

Terrain-Following Sampling
^^^^^^^^^^^^^^^^^^^^^^^^^^

This optional block lets the user emit an arbitrary number of point
clouds sampled from an STL surface or a plain-text/CSV point list.
Each source can be lifted to multiple offset "sheets" along a
user-provided normal, or along the per-facet normal read from an STL
file. Typical use cases: a mountain surface sampled at three
rotor-tip heights, or a hand-authored hub-height sample grid over an
irregular farm layout.

The block is optional. Legacy decks omit it entirely.

The block begins with the section header
``--- TERRAIN-FOLLOWING SAMPLING ---`` and is followed by:

- **NumTerrainSlices** [integer] specifies the number of
terrain-following slices (:math:`0` to :math:`99`).

- **WrTerrainDT** [sec] specifies the sampling period for this
feature. **DEFAULT** falls back to **DT_Low**. Independent of
both **WrDisDT** and **WrPlaneDT** so that heavy terrain samples
can be emitted less often than lighter axis-aligned slices.

- A two-line column header followed by **NumTerrainSlices** slice
rows with the following columns:

**SliceName** — quoted string. Free-form slice name; appears in
output file names.

**Offsets(m)** — comma- or whitespace-separated list of scalar
displacements (metres) along the **OffsetNormal**. Each value
spawns a separate sheet sharing the source geometry. An empty
list is equivalent to a single ``0``.

**OffsetNormal** — 3-vector, or the keyword ``default``. Unit
vector along which the offsets are applied. When ``default`` and
**SourceType** is ``STL``, the per-facet normal from the STL is
used instead. An explicit vector is required when **SourceType**
is ``Point``.

**SourceType** — keyword. ``STL`` reads an ASCII or binary STL
file and uses each facet's three vertices as sample points (no
de-duplication). ``Point`` reads a plain-text or CSV point cloud
file (see the point-cloud file format description below).

**FileName** — quoted string. Path to the STL or point-cloud
file. Relative paths are resolved against the FAST.Farm primary
input file directory.

Example row (two slices — a mountain lifted to three offset sheets
and a nine-point hub-height cloud):

.. code-block:: none

--- TERRAIN-FOLLOWING SAMPLING ---
2 NumTerrainSlices - Number of terrain-following slices (-)
DEFAULT WrTerrainDT - Sampling period (s) or DEFAULT (=DT_Low)
SliceName Offsets(m) OffsetNormal SourceType FileName
(-) (m,list) (-,-,-|dflt) (STL|Point) (quoted)
"terr" 50 100 150 default STL "mountain.stl"
"hub" 0.0 (0 0 1) Point "hub_points.txt"

**Point-cloud file format.** Plain ASCII, one point per line, three
floating-point columns ``x y z`` in metres in the FAST.Farm global
coordinate frame. Delimiter is whitespace or comma (both ``.txt`` and
``.csv`` are handled by the same parser). Comments are lines whose
first non-blank character is ``#`` or ``!``; trailing comments are
also allowed. Blank lines are ignored. An optional header row is
tolerated as long as it fails numeric parsing (this lets ``.csv``
exports with an ``x,y,z`` header row load unchanged). Column order is
fixed to ``x y z``. Point count is derived from the file — no
``NumPoints`` header is required. Duplicate points are not
de-duplicated (unlike STL vertices).

Output is written as VTK XML ``PolyData`` (``.vtp``) plus a matching
``.vtp.series`` sidecar. Any sample point falling outside the
low-resolution domain is written as IEEE quiet NaN, and an
``ErrID_Warn`` line is emitted at init reporting the count and
fraction. When a slice's total sample-location count
(``NPts × N_offsets``) is unusually large (currently
:math:`\ge 10\,000\,000`), an ``ErrID_Info`` size advisory is emitted
reporting the estimated RAM cost. No hard cap is imposed — the
NWTC-library allocator already fails cleanly with a byte-count message
if the OS refuses.

Output naming follows the pattern
``<RootName>.TerrSlice.<SliceName>.<n>.vtp`` with a companion
``<RootName>.TerrSlice.<SliceName>.vtp.series``, all under
``vtk_ff/``.

Output
~~~~~~

Expand Down
47 changes: 47 additions & 0 deletions docs/source/user/fast.farm/ModelGuidance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,53 @@ error universally across all aeroelastic software that use Mann boxes is
needed `future
work <https://github.com/OpenFAST/openfast/issues/256>`__.

.. _FF:sec:SliceOutputs:

Choosing a Visualization Slice Output
-------------------------------------

FAST.Farm ships three different slice-output paths, each with its own
place. Choose based on how much of the domain you need and how you plan
to load the output in ParaView.

**Classic slices** (**NOutDisWindXY** / **NOutDisWindYZ** /
**NOutDisWindXZ**, see :numref:`FF:Input:VTK`). These always span the
entire low-res domain and write legacy ASCII ``.vtk`` files with
``STRUCTURED_POINTS`` topology. Cheap to hand-author, but on a large
farm each XY hub-height slice is potentially the full farm cross
section — hundreds of megabytes per step, mostly of empty space.
Recommended: small farms; quick debugging; existing decks that already
use them.

**Extent-controlled axis-aligned slices** (**NumPlaneSlices**, see
:numref:`FF:Input:PlaneSlices`). Same axis-aligned uniform grid as
the classic slices, but each slice carries its own explicit 2-D extent
so a hub-height sheet can be kept to just the region of interest.
Output is XML ``.vts`` with a ParaView ``.vts.series`` sidecar for
straightforward time-series playback. Recommended for large-farm
runs where you know the region of interest, and for any new deck
that needs axis-aligned slices; use it in place of the classic
**NOutDisWindXY** / **YZ** / **XZ** blocks when disk-footprint or
per-slice extent control matters.

**Terrain-following point clouds** (**NumTerrainSlices**, see
:numref:`FF:Input:TerrainSlices`). Reads a surface (STL) or a bare
point list from disk and samples along user-provided offset sheets.
This is the only path that supports non-axis-aligned sampling
today — its typical uses are (i) sampling above a real mountain
surface at rotor-tip heights, (ii) sampling at hub height across an
irregular farm footprint, and (iii) validating that arbitrary
points in the domain carry the expected disturbed velocity. Output
is XML ``.vtp`` with a ``.vtp.series`` sidecar.

All three paths write into the ``vtk_ff/`` subdirectory of the deck
and are throttled independently: **WrDisDT** for the classic path,
**WrPlaneDT** for **NumPlaneSlices**, **WrTerrainDT** for
**NumTerrainSlices**. Each defaults to **DT_Low** if omitted, but
having independent knobs lets you (say) emit a heavy full-domain
slice once per minute while sampling a small hub-height sheet every
second.

.. _FF:sec:DiscRecs:

Low- and High-Resolution Domain Discretization
Expand Down
49 changes: 49 additions & 0 deletions docs/source/user/fast.farm/OutputFiles.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,55 @@ Each visualization output file follows the same VTK format used for the
ambient wind data files for the high-fidelity precursor simulations. See
:numref:`FF:AmbWindIfW` for details on the file format.

.. _FF:Output:PlaneSlices:

Extent-Controlled Axis-Aligned Plane Slices (Feature 2)
-------------------------------------------------------

If **NumPlaneSlices** is greater than zero in the FAST.Farm primary
input file (see :numref:`FF:Input:PlaneSlices`), one file per slice per
sampled step is written to *vtk_ff/* with naming
*<RootName>.Plane.<SliceName>.<n*\ :sub:`out`\ *>.vts* where
*<SliceName>* is the user-provided free-form name from the deck and
*<n*\ :sub:`out`\ *>* is a zero-padded step counter.

Each slice also has a companion ParaView time-series sidecar named
*<RootName>.Plane.<SliceName>.vts.series* — a small JSON file listing
every ``.vts`` step and its simulation time. Loading the ``.series``
file in ParaView plays the whole slice as an animation.

The ``.vts`` format is VTK XML *StructuredGrid* with explicit point
coordinates and a 3-component ``Velocity`` field. Nodes whose
global-frame position falls outside the low-resolution domain carry
IEEE quiet NaN in the ``Velocity`` field; ParaView masks these
automatically without any extra filter.

The sampling period is set by **WrPlaneDT** in the deck (defaults to
**DT_Low**). It is independent of the classic **WrDisDT** so that
lightweight hub-height sheets can be emitted at a much higher rate
than heavier full-domain outputs.

.. _FF:Output:TerrainSlices:

Terrain-Following Point Cloud Slices (Feature 3)
------------------------------------------------

If **NumTerrainSlices** is greater than zero in the FAST.Farm primary
input file (see :numref:`FF:Input:TerrainSlices`), one file per slice
per sampled step is written to *vtk_ff/* with naming
*<RootName>.TerrSlice.<SliceName>.<n*\ :sub:`out`\ *>.vtp* and a
companion *<RootName>.TerrSlice.<SliceName>.vtp.series* sidecar.

The ``.vtp`` format is VTK XML *PolyData* with per-point coordinates
and a 3-component ``Velocity`` field. Each source vertex is
replicated once per offset sheet, so a slice with :math:`N` source
points and :math:`M` offsets writes :math:`N \cdot M` points per
step. Nodes whose sample location falls outside the low-resolution
domain are set to IEEE quiet NaN and masked by ParaView.

The sampling period is set by **WrTerrainDT** in the deck (defaults to
**DT_Low**).

Visualizing the ambient wind and wake interactions can be useful for
interpreting results and debugging problems. However, FAST.Farm will
generate many files per output option when **WrDisWind** = TRUE and/or
Expand Down
Loading