FAST.Farm slice output (terrain following, and arbitrary slice)#3392
FAST.Farm slice output (terrain following, and arbitrary slice)#3392andrew-platt wants to merge 36 commits into
Conversation
Add Write_Planes_WireFrame and PlaneCorners helper to emit each active wake plane's outline in the global frame using vtk_lines. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This is not complete, but contains some of the info.
The .vtk.series file is not working as expected yet.
The edge points on the wake planes were not getting updated. The loop limits were one point short.
New guidance for calculating with larger safety factors, and different calculation for catesian+curl than polar. Co-authored-by: Regis Thedin <registhedin@gmail.com>
WD: fix smooth tapering from `numDFull` to `numDBuff` for curled wake
- Create modules/awae/src/AWAE_vtk.f90 containing module AWAE_vtk with all wake-plane VTK output routines: PlaneAxes, PlaneCorners, Write_Planes_WireFrame, Write_Planes_Data, Write_WakePlane_Data_File, Write_WakePlane_Series, and Write_NullPlane. - Remove those routines from AWAE_CalcOutput's internal contains block and convert them to standalone module subroutines with explicit arguments (p, u, m, n, t, Tstr) replacing host association. - Move the per-step Write_WakePlane_Series call from AWAE_CalcOutput to AWAE_End, writing series files once at shutdown instead of every output step. Merge the former two-routine pattern (Write_WakePlane_Series + Write_AllWakePlane_Series) into a single Write_WakePlane_Series(p, m). - Extract the inline null-plane block into Write_NullPlane subroutine. - Remove unused variables: FmtStr argument, PlaneNum, fileExists, rootDir from the former Write_WakePlane_Series. - Add AWAE_vtk.f90 to CMakeLists.txt and vs-build project; add 'use AWAE_vtk' to module AWAE. Co-authored-by: GitHub Copilot <175728472+Copilot@users.noreply.github.com>
…s files Add a new routine Write_WireFrame_Series(p) to AWAE_vtk that writes one ParaView .vtk.series index file per turbine for the WakePlanesWireFrame VTK outputs. Called once at shutdown from AWAE_End alongside the existing Write_WakePlane_Series call. Co-authored-by: GitHub Copilot <175728472+Copilot@users.noreply.github.com>
Add Write_DisWind_Series to AWAE_vtk module to generate ParaView .vtk.series index files for Low-resolution disturbed-wind XY, YZ, and XZ output slices. The routine is called from AWAE_End for each valid slice, matching the existing pattern for wake-plane and wireframe series files. Co-authored-by: GitHub Copilot <noreply@github.com>
…dels In WD_CalcOutput, the firstPass branch computed y%Vx_wake (polar) via NearWakeCorrection but never populated y%Vx_wake2 for Cartesian/Curl models. Additionally, the unconditional Cartesian/Curl taper block overwrote y%Vx_wake2 with xd%Vx_wake2 (still zeros) on firstPass, discarding any values set earlier. Changes: - Add Axisymmetric2CartesianVx conversion in the firstPass block of WD_CalcOutput to populate y%Vx_wake2 for Curl/Cartesian models. - Guard the Cartesian/Curl taper block with (.not. OtherState%firstPass) so it does not overwrite the firstPass initialization. - Add Mod_Wake guard and NearWakeCorrection call in InitStatesWithInputs for Cartesian/Curl state initialization. - Remove unused GridTol parameter in AWAE.f90. Co-authored-by: andrew-platt <andy.platt@nrel.gov>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
I thought this was in the outer context, but apparently not. Not sure how it was still compiling ok during testing.
- Changed planeDomainExit from a scalar to a 3-element array (one per spatial dimension) so a plane can be tracked as out-of-bounds in multiple dimensions simultaneously (e.g. exiting at a corner). - Split boundary-check logic to handle X, Y, Z independently in a loop. - Changed out-of-bounds velocity to reach target in one timestep (was 2). - Updated Registry, Types, and allocation to match new 3D shape. Co-authored-by: GitHub Copilot <noreply@github.com>
…rging - Added y%wakePlaneDomainExit (ReKi, 3 x planes x turbines) to AWAE OutputType, populated from m%planeDomainExit after LowResGridCalcOutput. - Added u%wakePlaneDomainExit (ReKi, 3 x planes) to WD InputType. - Transfer in glue-code Transfer_AWAE_to_WD. - Added out-of-bounds plane merging in WD_UpdateStates: consecutive planes that are both out of domain and within 2*dr of each other (Euclidean) are averaged and collapsed iteratively from highest to lowest index. - Extracted common merge+shift logic into contained subroutine MergeWakePlanes(iKeep, iDrop), used by both overtake and OOB merging. - Used ReKi for the input/output arrays (framework differentiability requirement); NINT used for comparisons in WD. Co-authored-by: GitHub Copilot <noreply@github.com>
Change time declaration from real(ReKi) to real(DbKi) to match amrex_read_header signature. Use _ReKi kind for gridSpacing, gridSize, and bounds literal constants instead of _c_double. Co-authored-by: GitHub Copilot <noreply@github.com>
…f tail truncation Rewrite the buffer-exit plane-dropping logic so that each plane beyond x_Buff is individually removed and higher-indexed planes are shifted down. This replaces the previous approach that simply decremented NumPlanes (effectively dropping the last plane), which assumed the highest-indexed plane had always travelled the furthest. Extract the array-shifting loop from MergeWakePlanes into a new ShiftWakePlanesDown subroutine shared by both MergeWakePlanes and the buffer-drop loop. Co-authored-by: GitHub Copilot <copilot@github.com> Co-authored-by: Claude (Anthropic) <claude@anthropic.com>
Move the domain-exit check for wake plane merging from an AWAE-computed per-plane flag (wakePlaneDomainExit) to a direct bounds test using the low-resolution grid bounds stored as a WakeDynamics parameter. - Add LowResBounds(3,2) to WD InitInputType and ParameterType (index 1 = XYZ dimension, index 2 = lower/upper bound). - Populate LowResBounds in FAST_Farm_Subs from AWAE init outputs (oXYZ_low, dXYZ_low, nXYZ_low) before calling WD_Init. - Add PlaneOutOfBounds() pure function in WD_UpdateStates that tests plane center position against p%LowResBounds directly. - Remove wakePlaneDomainExit from WD InputType, AWAE OutputType, and the Transfer_AWAE_to_WD glue-code transfer. - Remove dead LowRes%Center field from AWAE LRGParamType. Co-authored-by: GitHub Copilot <copilot@github.com> Co-authored-by: Claude (Anthropic) <claude@anthropic.com>
…utput
Adds three pieces of dead-code infrastructure that later commits wire into
the new VISUALIZATION features (NumPlaneSlices, NumTerrainSlices):
* modules/awae/src/AWAE.f90
ExtractSliceSub - bounded variant of ExtractSlice that populates a
subregion [i_lo:i_hi, j_lo:j_hi] of an axis-aligned slice. Used by
the axis-aligned planar sampling feature (Feature 2).
* modules/awae/src/AWAE_IO.f90
WriteVTK_PolyData - writes a single-piece VTK XML PolyData (.vtp)
file for a point cloud with a 3-component vector field. NaN in the
field is accepted (ParaView masks it). Used by the terrain-following
feature (Feature 1).
WriteVTK_StructuredGrid_2D - writes a 2-D VTK XML StructuredGrid
(.vts) file with explicit points and a 3-component vector field.
Used by Feature 2 when VTKFormat=xml.
VTK_Series_Open / VTK_Series_Append / VTK_Series_Close - trio for
incrementally writing a ParaView .series JSON sidecar so the two
features can emit time-varying VTK series without buffering the
full step list. Used by both Features 1 and 2.
None of the new symbols has a caller yet; all existing tests behave
identically. Verified with ctest -L fastfarm against the LESinflow deck
(passes) and the multi-turbine AMReX / ModAmb_3 / MD_Shared decks
(all pass). Three tests are still failing on tolerance drift because
the r-test gold baselines were captured with double-precision + OpenMP;
those pass on build-docker-double per the plan.
Also includes FF_output_features_plan.md, the multi-round design plan
for the two new output features, so future reviewers can see the
motivating requirements and locked-in design decisions.
Co-authored-by: GitHub Copilot <copilot@github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Adds a new '--- AXIS-ALIGNED PLANE SLICES (extent-controlled) ---' block
to the FAST.Farm primary input file that lets the user emit an arbitrary
number of axis-aligned uniform-grid VTK slices, each with a
user-controlled 2-D extent placed anywhere in the low-res domain.
Grammar follows plan-file Snippet 6 (OpenFOAM-inspired origin + normal
+ extent1 + extent2). Output is XML VTK .vts + .vts.series so ParaView
can play the time series without buffering the full step list.
Registry-level additions (flat arrays rather than a derived slice type,
to keep the auto-generated pack/unpack code inside the compiler's memory
budget on this container):
* AWAE_InputFileType: NumPlaneSlices, WrPlaneDT, PlaneSliceName/Origin/
Normal/Extent1/Extent2
* AWAE_ParameterType: NumPlaneSlices, WrPlaneSkp, PlaneSliceName,
PlaneSliceOrigin, PlaneSliceNormalAxis/Axis1/Axis2/N1/N2/ILo/IHi/
JLo/JHi/Valid/SeriesUn
* AWAE_MiscVarType: PlaneSliceStepCount, LastPlaneSliceN (scalar guard
against Farm_InitialCO calling AWAE_CalcOutput twice at t=0)
Code additions (all in modules/awae/src/AWAE.f90 and AWAE_IO.f90):
* ValidatePlaneSlices - init-time normal check (fatal on off-axis with
the exact plan §3.7 error text pointing to the future point-cloud
feature), extent-positivity check, derives (Axis1, Axis2, N1, N2)
from the low-res spacing, requested (i_lo, i_hi, j_lo, j_hi) index
window (may be out-of-domain -> emit fills with NaN), and opens the
.vts.series sidecar for each valid slice.
* EmitPlaneSlices - per-step VTK emitter, called from AWAE_CalcOutput
at every mod(n, p%WrPlaneSkp)==0. Pre-fills sample buffer with IEEE
quiet NaN, then uses ExtractSliceSub (from the Phase 1 foundation)
to fill only the in-domain window; writes .vts + appends to
.vts.series.
* VTK_Series_Close wiring in AWAE_End.
* MKDIR condition extended to include NumPlaneSlices>0 so the vtk_ff/
directory is created even when the classical NOutDisWind* slices
are disabled.
* One trivial format-string fix in VTK_Series_Append (had one too
many 'A' items).
Parser (FAST_Farm_IO.f90):
* ReadPlaneSlicesBlock - optional block reader with backspace-and-
return path when the block header is absent (legacy decks stay
inert). Tolerates parenthesised vectors and commas for the
(origin), (normal) columns. Comment characters '!' and '#' allowed
in slice rows.
Reg-test:
* reg_tests/CTestList.cmake gains one ff_regression() line for
LESinflow_ArbSlice. r-test submodule is bumped to the commit that
contains the deck under
glue-codes/fast-farm/LESinflow_ArbSlice/.
* The deck's turbine physics and OpenFAST outputs are identical to
the LESinflow deck by construction, so its baseline .out / .T1.outb
are the LESinflow originals; only new VTK slice files are produced.
Verified with:
cd build-docker-single-debug && ctest -L fastfarm --output-on-failure
# 5 pass (LESinflow, LESinflow_ArbSlice, AMReX, ModAmb_3, MD_Shared)
# 3 fail on the pre-existing single-precision-vs-double-precision
# tolerance drift (TSinflow, TSinflow_curl, TSinflowADskSED) - these
# were failing before Phase 1/2 and will pass in build-docker-double
# per §10.2 of the plan.
The vts.series sidecar for the new deck is clean (no duplicate at t=0
thanks to the LastPlaneSliceN scalar guard).
Co-authored-by: GitHub Copilot <copilot@github.com>
Co-authored-by: Claude <noreply@anthropic.com>
…inSlices)
Adds a new '--- TERRAIN-FOLLOWING SAMPLING ---' block to the FAST.Farm
primary input file that lets the user emit an arbitrary number of point
clouds sampled from an STL surface or a plain-text/CSV point list, each
optionally lifted to multiple offset sheets along a user-provided (or
STL-per-facet) normal. Output is XML VTK .vtp + .vtp.series so ParaView
can play the time series with correct NaN masking for points outside the
low-res domain.
Input grammar (pdf §2.8, with the SourceType/FileName column pair the
user requested during plan review):
--- TERRAIN-FOLLOWING SAMPLING ---
<NumTerrainSlices> NumTerrainSlices [0..99]
<WrTerrainDT | DEFAULT> WrTerrainDT (defaults to WrDisDT)
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"
Registry additions (flat/packed arrays -- same design as Feature 2 --
to keep the auto-generated pack/unpack code inside the compiler's memory
budget on this container):
* AWAE_InputFileType: NumTerrainSlices, WrTerrainDT, TerrainSliceName,
TerrainSliceSourceType (1=STL / 2=Point), TerrainSliceFileName,
TerrainSliceOffsetNormal, TerrainSliceOffsetsPacked +
TerrainSliceOffsetIdx (packed ragged offsets)
* AWAE_ParameterType: NumTerrainSlices, WrTerrainSkp, TerrainSliceName,
TerrainSliceValid, TerrainSliceSeriesUn, TerrainSliceNPtsTotal,
TerrainSlicePtsIdx, TerrainSlicePtsFlat (packed per-slice point
coordinates, all offsets embedded)
* AWAE_MiscVarType: TerrainSliceStepCount (per-slice isFirst counter)
+ scalar LastTerrainSliceN guard against Farm_InitialCO's double
t=0 CalcOutput
New code (modules/awae/src/AWAE.f90):
* ReadSTLFile - reads ASCII or binary STL and returns per-vertex
coordinates + facet normals (the same normal is replicated across
the three vertices of each facet). Auto-detects ASCII vs binary
from the header. No de-duplication (deliberate: keeps output
faithful to the source mesh).
* ReadPointCloudFile - reads plain-text or comma-delimited x y z per
line; tolerates leading comment (# or !) rows and one optional
header row (any line that fails numeric parsing before the first
data row is silently skipped). Fails fast on a malformed row
once data has started, per plan §2.2.1.
* ValidateTerrainSlices - reads each slice's file, expands with the
per-slice offsets (using the STL per-facet normal when
OffsetNormal=0 sentinel, else the global vector), packs the
resulting points into p%TerrainSlicePtsFlat, opens each valid
slice's .vtp.series sidecar, emits an ErrID_Info size advisory
above 10 M sample locations (per plan §2.2.2 no-hard-cap policy),
and emits an ErrID_Warn describing the fraction of the slice that
will be NaN-filled when it straddles the domain boundary.
* EmitTerrainSlices - per-step trilinear-samples m%Vdist_low_full at
every pre-computed point (NaN for out-of-domain), writes a .vtp
per slice, appends to the .vtp.series sidecar.
* MKDIR condition extended: vtk_ff/ is now created when either
NumPlaneSlices or NumTerrainSlices > 0, in addition to the
original legacy triggers.
* VTK_Series_Close wiring added to AWAE_End.
Parser (glue-codes/fast-farm/src/FAST_Farm_IO.f90):
* ReadTerrainSlicesBlock - same optional-block pattern as
ReadPlaneSlicesBlock (backspaces on missing header for legacy
decks). Extracts the two quoted strings (name, filename) in order,
strips ( ) , delimiters, then tokenises the remaining row into
(offsets, [normal|"default"], SourceType). The variable-length
offsets list is inferred from the token count.
Reg-test:
* reg_tests/CTestList.cmake gains one ff_regression() line for
LESinflow_TerrainSlice. r-test submodule bumped to the commit
that contains the deck (glue-codes/fast-farm/LESinflow_TerrainSlice/)
together with two small hand-authored source files:
- mountain.stl (ASCII, 4-facet pyramid centred on the turbine)
- hub_points.txt (9-point CSV with header, exercises both
delimiter paths)
* Deck exercises both SourceType paths, both OffsetNormal modes
(per-facet default vs explicit vector), and the ragged-offsets
packed layout (3 offsets on one slice, 1 on the other).
Verified with:
cd build-docker-single-debug && ctest -L fastfarm --output-on-failure
# 6 pass (LESinflow, LESinflow_ArbSlice, LESinflow_TerrainSlice,
# AMReX, ModAmb_3, MD_Shared)
# 3 fail on the pre-existing single-precision-vs-double-precision
# tolerance drift (TSinflow, TSinflow_curl, TSinflowADskSED) -
# unchanged from Phase 1/2 and will pass in build-docker-double
# per §10.2 of the plan.
Sample output for the mountain slice at t=0 verified: 3*(3*4)=36
points per timestep, coordinates match hand-computed vertex+offset*normal
for each facet. Series sidecar is clean (no duplicate at t=0 thanks
to the LastTerrainSliceN scalar guard).
Co-authored-by: GitHub Copilot <copilot@github.com>
Co-authored-by: Claude <noreply@anthropic.com>
…ocks
Adds the user-facing documentation for the two new VISUALIZATION
sub-sections introduced by commits 77abd9298 (Feature 2, axis-aligned
extent-controlled planar sampling) and 8037df4ea (Feature 3,
terrain-following point-cloud sampling) on branch f/FF_sliceOutput.
Touched files:
* docs/source/user/fast.farm/InputFiles.rst
Two new subsections after the classic '--- VISUALIZATION ---'
block: 'Axis-Aligned Plane Slices (extent-controlled)' and
'Terrain-Following Sampling', each with the block grammar as a
definition list (avoids RST simple-table alignment pitfalls),
one worked example, and the semantics of the point-cloud file
format (whitespace/CSV, comments, optional header row, no de-dup).
* docs/source/user/fast.farm/OutputFiles.rst
Two new subsections describing the '.vts' + '.vts.series' and
'.vtp' + '.vtp.series' outputs, the NaN-masking convention for
out-of-domain nodes, and the independent WrPlaneDT / WrTerrainDT
sampling rates.
* docs/source/user/fast.farm/ModelGuidance.rst
New 'Choosing a Visualization Slice Output' section that guides
users among the three paths (classic NOutDisWind*, NumPlaneSlices,
NumTerrainSlices) and their independent sampling rates.
* docs/source/user/fast.farm/FutureWork.rst
New bullet on extending NumPlaneSlices to accept arbitrary
non-axis-aligned planes, referencing issue OpenFAST#2383 - so the fatal
error text emitted by ValidatePlaneSlices for off-axis normals has
a matching documented forward pointer.
* docs/source/user/api_change.rst
New v5.0.x-to-next-release entry describing the two new optional
VISUALIZATION sub-sections, cross-referenced to the new subsections
in InputFiles.rst and the guidance section in ModelGuidance.rst.
Verified: docutils parses every touched file with only the pre-existing
Sphinx-role warnings (numref, cite, eq, download, ref) - my additions
introduce no new RST syntax errors. Full Sphinx build wasn't run in
this container (Sphinx 5.3 in the Python 3.13 env needs an imghdr
compat shim that isn't installed), but that's an environment issue
unrelated to these edits.
Removed the development plan for these features.
Co-authored-by: GitHub Copilot <copilot@github.com>
Co-authored-by: Claude <noreply@anthropic.com>
|
Note: as posted there are a lot of merge conflicts. This was developed off of branch |
There was a problem hiding this comment.
Pull request overview
This pull request extends FAST.Farm’s visualization/output capabilities by adding new slice-output options (extent-controlled axis-aligned planar sampling and terrain-following point-cloud sampling) with ParaView-friendly XML VTK outputs and streamed .series time-index sidecars, while also updating wake/VTK infrastructure and regression coverage to support and validate the new outputs.
Changes:
- Adds new FAST.Farm VISUALIZATION blocks for
NumPlaneSlicesandNumTerrainSlices, including parsing, runtime state, and XML VTK output (.vts/.vtp) with streamed.seriessidecars. - Introduces/updates AWAE VTK writer infrastructure (new
AWAE_vtk.f90, new XML writers and.serieshelpers inAWAE_IO.f90, updated generated types/registry). - Updates FAST.Farm regression test registration and documentation for the new input/output features.
Reviewed changes
Copilot reviewed 20 out of 24 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| vs-build/modules/AWAE.vfproj | Adds AWAE_vtk.f90 to the Visual Fortran project sources. |
| reg_tests/CTestList.cmake | Registers two new FAST.Farm regression tests for the new slice-output features. |
| modules/wakedynamics/src/WakeDynamics.f90 | Updates wake-plane lifecycle/merging/removal logic and initializes additional state fields. |
| modules/wakedynamics/src/WakeDynamics_Types.f90 | Adds LowResBounds to init/parameter types and updates pack/unpack/copy routines. |
| modules/wakedynamics/src/WakeDynamics_Registry.txt | Declares LowResBounds in the WakeDynamics registry for code generation. |
| modules/awae/tests/test_AMReX_reader.f90 | Adjusts test scalar kinds/constants for time and grid calculations. |
| modules/awae/src/AWAE_vtk.f90 | Adds AWAE VTK output module (wake plane files + .vtk.series generation). |
| modules/awae/src/AWAE_Types.f90 | Regenerated AWAE types/pack/unpack to include new slice feature fields and updated VTK root naming. |
| modules/awae/src/AWAE_Registry.txt | Extends AWAE registry with new slice inputs/runtime state and clarifies misc/param field semantics. |
| modules/awae/src/AWAE_IO.f90 | Adds XML VTK writers (.vtp, .vts) and streamed .series helpers; updates disturbed-wind output root naming. |
| modules/awae/CMakeLists.txt | Adds AWAE_vtk.f90 to the AWAE static library build. |
| glue-codes/fast-farm/src/FAST_Farm_Subs.f90 | Adjusts MaxNumPlanes logic and passes low-res domain bounds into WakeDynamics init input. |
| glue-codes/fast-farm/src/FAST_Farm_IO.f90 | Adds optional parsing blocks for plane slices and terrain slices (backspace-and-return behavior for legacy decks). |
| docs/source/user/fast.farm/OutputFiles.rst | Documents new .vts/.vtp outputs and .series sidecars for the added slice features. |
| docs/source/user/fast.farm/ModelGuidance.rst | Adds guidance on choosing between classic slices, extent-controlled planes, and terrain-following point clouds. |
| docs/source/user/fast.farm/InputFiles.rst | Documents the new VISUALIZATION sub-block grammars and point-cloud file format. |
| docs/source/user/fast.farm/FutureWork.rst | Notes future extension toward arbitrary-orientation planar sampling. |
| docs/source/user/api_change.rst | Records the new optional FAST.Farm input blocks as an API/input change. |
| .gitignore | Ignores common devcontainer/VSCodedocker workspace files. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (m%WakeVTK_StartN(np_wp, nt_wp) > out_idx) then | ||
| EntryName = trim(p%OutFileFFvtkWakeNullData) | ||
| else | ||
| EntryName = trim(baseName)//"."//trim(VTKprefix)//"."//trim(TstrOut)//".vtk" | ||
| endif |
| ! The row has (up to) TWO double-quoted strings: the slice name (first) | ||
| ! and the filename (second/last). Extract in order. | ||
| call ExtractQuoted( work, sliceName ) | ||
| if (len_trim(sliceName) == 0) then | ||
| call ExtractBareToken( work, sliceName ) | ||
| end if | ||
| if (len_trim(sliceName) == 0) then | ||
| err = ErrID_Fatal; msg = 'Missing slice name.' | ||
| return | ||
| end if |
| tokCount = tokCount + 1 | ||
| offList(tokCount) = rval | ||
| if (tokCount > size(offList)) then | ||
| err = ErrID_Fatal; msg = 'Too many offsets on a single line.' | ||
| return | ||
| end if |
| write(Un,'(A)') '<!-- '//trim(descr)//' -->' | ||
| write(Un,'(A)') '<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian">' | ||
| write(Un,'(A)') ' <PolyData>' | ||
| write(Un,'(A,I0,A)') ' <Piece NumberOfPoints="', N, '" NumberOfVerts="1" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="0">' |
| write(Un,'(A)') ' <DataArray type="Int64" Name="offsets" format="ascii">' | ||
| write(Un,'(1X,I0)') N | ||
| write(Un,'(A)') ' </DataArray>' |
|
Todo (@andrew-platt)
|
Fixes compile/lint warnings from type and argument shadowing on the rebased branch: - Rename local dummy argument 'name' to 'nameOut' in FAST_Farm_IO.f90 helpers (ExtractQuotedName, ExtractQuoted) to avoid masking parent scope variables. - Rename local variable 'nan' to 'nan_val' in AWAE.f90 handlers (EmitPlaneSlices, EmitTerrainSlices) to resolve shadowing of the module-level constant from NWTC_Library. Co-authored-by: Google Gemini 3.5 Flash <gemini@google.com> Co-authored-by: GitHub Copilot <copilot@github.com>
|
Thanks for adding these new visualization features! Just a few comments:
|
Not ready to merge. See merge order below
Co-authored-by: Regis Thedin registhedin@gmail.com - conceptual development and multi-round plan iteration
Feature or improvement description
Adds two new FAST.Farm
VISUALIZATIONoutput features requested by the "Large Wind Farm Task" (§2.8 and §2.9) and issue #2383. Both are gated by dedicated block headers so existing FAST.Farm input files remain unchanged.NumPlaneSlices— axis-aligned, extent-controlled planar sampling (Snippet 6 grammar from the plan). Each slice is defined by anorigin(m), an axis-alignednormal, and two in-planeextent(m)values. The sample grid is fixed to the low-res spacing (dX_Low/dY_Low/dZ_Low), so nonpointscolumn is required. Off-axis normals are a fatal input error whose message forward-references the future point-cloud extension.NumTerrainSlices— terrain-following point-cloud sampling from an STL surface or a plain-text point cloud, each swept along one or moreOffsets(m)in anOffsetNormaldirection (facet-normal by default for STL). Every sample point is trilinearly interpolated in the low-res disturbed wind field at each output step.Both features write self-describing XML VTK output (
.vtsStructuredGridfor planar slices,.vtpPolyDatafor point clouds) plus a matching.seriesJSON sidecar for ParaView's built-in time-series loader. Out-of-domain sample nodes are masked with IEEE quiet NaN so ParaView clips them automatically.Each feature has its own sampling period (
WrPlaneDT,WrTerrainDT) that falls back toWrDisDTviaDEFAULT, so users can sample the two feature streams at rates independent of the classic disturbed-wind output.Feature 1 — three axis-aligned planes (conceptual and real output)
The
LESinflow_ArbSlicereg-test deck plants three slices: a horizontalhubXYplane (red, normal(0,0,1)), a cross-streamcrossYZplane through the turbine (green, normal(1,0,0)), and a stream-wisecrossXZplane (blue, normal(0,1,0)). All three intersect at the WT1 turbine.Above: horizontal$t = 24$ s parsed directly from $121 \times 61$ nodes on the low-res spacing ($(1000, 1000)$ .
hubXYplane atFAST.Farm.Plane.hubXY.008.vts. The plane is discretised atdX_Low = dY_Low = 10 m); the wake deficit downstream of WT1 shows up as the dark low-velocity patch centred atInput file syntax (from the reg-test deck):
Feature 2 — STL mountain + hub cloud (conceptual and real output)
The
LESinflow_TerrainSlicereg-test deck plants two slices:"terr"— a 4-facet pyramid mountain read frommountain.stl(12 vertices, one per STL facet corner), swept along the per-facet normal to three offset sheets at 50/100/150 m. Total sample count:"hub"— a 9-point hand-authored point cloud read fromhub_points.txt, one sheet at offset 0 with an explicit verticalOffsetNormal (0 0 1). Exercises the CSV-with-header parser path inReadPointCloudFile.Above: sampled velocity magnitude at$t = 24$ s parsed from
FAST.Farm.TerrSlice.terr.008.vtp(green circles, 36 pts across three offset sheets) andFAST.Farm.TerrSlice.hub.008.vtp(blue squares, 9 pts at hub height). The underlying pyramid is drawn faint for scale.Input file syntax (from the reg-test deck):
Related issue, if one exists
Closes / addresses #2383 (parts pt. 1 = axis-aligned planar sampling, pt. 2 = terrain-following point cloud). The full design plan lives in
FF_output_features_plan.mdon the branch and cross-references the same issue.Impacted areas of the software
modules/awae/src/AWAE.f90ExtractSliceSub(bounded variant ofExtractSlice),ValidatePlaneSlices,EmitPlaneSlices,ReadSTLFile,ReadPointCloudFile,ValidateTerrainSlices,EmitTerrainSlices. Init calls bothValidate*after existing slice validation; End closes both feature's.seriessidecars.modules/awae/src/AWAE_IO.f90WriteVTK_PolyData(.vtp),WriteVTK_StructuredGrid_2D(.vts), streamingVTK_Series_Open/_Append/_Closefor.seriesJSON sidecars.modules/awae/src/AWAE_Registry.txtInputFileType/ParameterType/MiscVarTypefor both features (flat rather than array-of-derived-type — see design notes below).modules/awae/src/AWAE_Types.f90glue-codes/fast-farm/src/FAST_Farm_IO.f90ReadPlaneSlicesBlockandReadTerrainSlicesBlock(both use backspace-and-return for missing headers, so pre-existing decks continue to parse unchanged).reg_tests/CTestList.cmakeff_regressionentries —LESinflow_ArbSliceandLESinflow_TerrainSlice.reg_tests/r-testsubmodule bump to64feb0011docs/source/user/fast.farm/InputFiles.rst,OutputFiles.rst,ModelGuidance.rst,FutureWork.rst,api_change.rst.Plane.<name>.<t>.vts,.TerrSlice.<name>.<t>.vtp, matching.seriessidecars), NaN masking, and the independent sampling-rate story.FutureWorklinks back to #2383 for the arbitrary-orientation extension.Additional supporting information
Commit layout on this branch (4 logical commits on top of
b/FF_wake_start_noise):12af71a69eff99bcddNumPlaneSlices)e7ace15fdNumTerrainSlices)cdfb61065NumPlaneSlices/NumTerrainSlicesblocksDesign notes worth calling out at review:
AWAE_PlaneSliceType/AWAE_TerrainSliceType. An earlier draft used derived types for the per-slice state, but the generated per-elementpack/unpackinFAST_Farm_Types.f90blew past the 7.7 GiB container's memory ceiling duringf951code-gen. The switched design usesPlaneSliceOrigin(3,:)/PlaneSliceExtent1(:)/ etc. plus a prefix-sumTerrainSliceOffsetIdx(:)into a packedTerrainSliceOffsetsPacked(:)— the ragged offsets stay ragged without paying the derived-type registry cost.t = 0.Farm_InitialCOcallsAWAE_CalcOutputtwice atm%LastPlaneSliceN/m%LastTerrainSliceNinitialised to-1; theEmit*routines early-return whenm%Last*N == nso the identical.vts/.vtpfile isn't rewritten and the.seriessidecar doesn't get a duplicatet=0entry.EmitPlaneSlicespre-fills the write buffer withieee_value(0.0_SiKi, ieee_quiet_nan), then calls the boundedExtractSliceSubfor only the in-domain window[iLoE, iHiE] × [jLoE, jHiE].EmitTerrainSlicesNaN-fills any point whose[oXYZ, oXYZ + (nXYZ-1)·dXYZ]. ParaView masks these automatically.docs/source/user/fast.farm/FutureWork.rst).Conceptual overlap with the existing
AWAE_vtk.vtk.serieswriter. During the rebase ontob/FF_wake_start_noise(see "Test results" below) it became clear that this branch'sAWAE_IO.f90::VTK_Series_Open/_Append/_Closehelpers and the base branch'sAWAE_vtk.f90::Write_DisWind_Series/Write_WakePlane_Series/Write_WireFrame_Seriesboth emit ParaView.seriesJSON sidecars, but with materially different flow patterns:AWAE_vtk(base branch)AWAE_IO(this PR)AWAE_Endafter the runOpenat Init,AppendeachCalcOutput,Closeat End.vtk.series(legacy VTK).vts.series/.vtp.series(XML VTK)0..NumDT/WrDisSkp1No literal duplicate code and both routines coexist without collision on the merged branch, but a future cleanup PR could consolidate them into a single
AWAE_vtkinterface (streaming API for both) — kept out of this PR to hold the rebase minimal.Generative AI usage
Substantial portions of this PR — implementation across all 4 phases, rebase conflict resolution onto
b/FF_wake_start_noise, and reg-test deck authoring — were generated with AI assistance. Co-author trailers are on every commit.Co-authored-by: Anthropic Claude Opus 4.7 claude@anthropic.com
Co-authored-by: Google Gemini 3.5 Flash gemini@google.com
Co-authored-by: GitHub Copilot copilot@github.com
Test results, if applicable
reg_tests/r-testsubmodule pointer from14c0e913e(b/FF_wake_start_noise) to64feb0011(r-testf/FF_sliceOutput, 2 commits:7be23c16eLESinflow_ArbSlicedeck +64feb0011LESinflow_TerrainSlicedeck). See companion r-test PR.Full FAST.Farm regression suite in
build-docker-double(double-precision,AMREX_READER=ON,RelWithDebInfo):Output verification. For each new deck, the per-step
.vts/.vtpfiles were spot-checked by parsing the XML and confirming (a) node coordinates match the inputorigin + i·d_axis/Pts + Offset·OffsetNormalarithmetic to machine precision, (b).seriessidecars have exactly one entry perCalcOutputinvocation with monotonically increasingtime, and (c) no duplicatet = 0entry from the double-call insideFarm_InitialCO.Merge order
devdevto this branch