Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9d1df41
GAD tutorial - commit 1
domingom Oct 15, 2025
5bb19bf
commit 2
domingom Oct 15, 2025
7a86c68
Commit 3
domingom Oct 15, 2025
89ae0c8
commit 3
domingom Oct 15, 2025
5025bf2
commit 4
domingom Oct 15, 2025
dfd746d
commit 5
domingom Oct 15, 2025
3c5efa7
commit ref
domingom Oct 15, 2025
3987c00
fixing some typos
domingom Oct 15, 2025
06df593
fix to reference
domingom Oct 15, 2025
777f6be
Include a params.in file for the GAD tutorial, some additions to the …
domingom Oct 16, 2025
ad9aafa
Fix the table value for default GADaxialInduction
domingom Oct 16, 2025
8d901e5
urban tutorial
domingom Oct 17, 2025
9057843
params file for urban tutorial
domingom Oct 17, 2025
4f39a68
commit to urban tutorial
domingom Oct 17, 2025
843c722
typos fix
domingom Oct 17, 2025
ac26f49
fix to the description of wq saying sensible instead of latent in all…
domingom Oct 17, 2025
b5e3bf2
Updated gad/urban plots, fix to Example10 params file and adjustments…
domingom Oct 20, 2025
1bf4ce8
Shorter GAD tutorial title
domingom Oct 20, 2025
ce2b4a9
removed references from gad/urban and added comments from Jeremy on t…
domingom Oct 20, 2025
dd6077b
Revised Tutorials, adjusting names, adding Model Extensions, etc.
jsauer-NCAR Oct 21, 2025
0b26b40
added orphan tag to sensitivity.rst to fix doc build error
jsauer-NCAR Oct 21, 2025
a04bbda
Added transistion text after toctree and before sensitivity tests.
jsauer-NCAR Oct 21, 2025
f547732
Removed section number and polished a few words.
jsauer-NCAR Oct 21, 2025
87fd2d3
Added blank line after rubric to fix build-doc eror
jsauer-NCAR Oct 21, 2025
f9ef219
Set rubric heading for sensitivity tests
jsauer-NCAR Oct 21, 2025
0eecd35
Updated GAD and URBAN images from Domingo plus a test of a pointer to…
jsauer-NCAR Oct 21, 2025
e6d9813
Fixed path to publications.rst
jsauer-NCAR Oct 21, 2025
e847957
remove .rst from target_file link
jsauer-NCAR Oct 21, 2025
2f88259
Added pointer to citation references in Publications sectio to the do…
jsauer-NCAR Oct 21, 2025
9262bdd
Removed redundant extensions case list
jsauer-NCAR Oct 21, 2025
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
33 changes: 28 additions & 5 deletions docs/Tutorials/cases.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
****************
Ideal Test Cases
****************
***********
Ideal Cases
***********

Seven test cases are described:
Seven idealized cases are provided:

* Dry neutral boundary layer
* Dry convective boundary layer
Expand All @@ -12,7 +12,7 @@ Seven test cases are described:
* Offshore boundary layer
* Passive scalar transport and dispersion over an idealized hill

Required tutorial resources including python utilities and Jupyter Notebooks are provided in the tutorials directory of the `FastEddy-model GitHub repository <https://github.com/NCAR/FastEddy-model>`_ with required data for the moist dynamics example available at this `Zenodo record <https://zenodo.org/records/10982246>`_. All test cases are idealized setups over flat terrain. For each case, the user will set up the input parameter file, execute FastEddy, visualize the output using a Jupyter notebook, and perform some basic analysis of the output. After examining the test cases, the user will carry out some sensitivity tests by changing various input parameters. The purpose of these tests are for the user to become more familiar with the input parameters, and how changes to those parameters affect the output. After the tutorial, the user is expected to have basic knowledge to carry out LES using FastEddy.
Resources required for tutorial cases including python utilities and Jupyter Notebooks are provided in the tutorials directory of the `FastEddy-model GitHub repository <https://github.com/NCAR/FastEddy-model>`_ with required data for the moist dynamics example available at this `Zenodo record <https://zenodo.org/records/10982246>`_. All cases are idealized setups over flat terrain. For each case, the user will set up the input parameter file, execute FastEddy, visualize the output using a Jupyter notebook, and perform some basic analysis of the output. After examining the cases, the user will carry out some sensitivity tests by changing various input parameters. The purpose of these tests are for the user to become more familiar with the input parameters, and how changes to those parameters affect the output. After completing these tutorials, the user will have some basic knowledge and capacity to carry out LES activites using FastEddy.

.. toctree::

Expand All @@ -23,3 +23,26 @@ Required tutorial resources including python utilities and Jupyter Notebooks are
cases/CANOPY.rst
cases/OFFSHORE.rst
cases/DISPERSION.rst

.. rubric:: Sensitivity Tests

* Re-run the neutral case with :math:`[N_x,N_y,N_z]=[400,400,122]` and isotropic grid spacings of :math:`[dx,dy,dz]=[10,10,10]`. Adjust the model time step accordingly. Re-make all plots and discuss the differences between the control case. How much longer did it take to complete the simulation?
* Re-run the convective case with a surface heat flux of :math:`=+0.70` Km/s. Re-make all plots and discuss the differences between the control case.
* Re-run the neutral case with :math:`z_0=0.3` m. Re-make all plots and discuss the differences between the control case.
* Re-run the neutral case with the first order upwind advection scheme. Re-make all plots and discuss the differences between the control case. Why is the first order scheme a bad choice?
* Re-run the stable case with a surface cooling rate of :math:`-0.5` K/h. Re-make all plots and discuss the differences between the control case.
* Re-run the stable case using half of the GPUs used in the control simulation. How much slower does the case run?

* Re-run the BOMEX case with a higher-order advection for water vapor (moistureAdvSelectorQv = 3). What is the impact of the increased effective resolution on dynamical, thermodynamical and microphysical quantities, along with turbulence variability and fluxes? How does that change influce the comparison to the other BOMEX LES models?

.. only

(Here, the user will make some modifications to the default parameters such as changing the grid spacing, stretching, model time step, advection

scheme, number of grid points, domain decomposition and number of GPUs, etc, etc. Here, the user will execute the sensitivity test, and visualize
and analyze the output)

x^2+y^2=z^2

frac{ sum_{t=0}^{N}f(t,k) }{N}

10 changes: 10 additions & 0 deletions docs/Tutorials/cases_extensions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*********************
Model Extension Cases
*********************

Two model extension cases are provided excercising the Generalized Actuator Disk (GAD) parameterized model and building-resolving URBAN model extensions respectively.

.. toctree::

cases_extensions/GAD.rst
cases_extensions/WRF_coupling_case0_FE_urban.rst
64 changes: 64 additions & 0 deletions docs/Tutorials/cases_extensions/GAD.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
=====================================
Turbine array flow with the GAD model
=====================================

This is an idealized scenario of wind farm (3 x 3 turbine array) flow in neutrally stratified boundary layer with an evolving wind direction spanning 90 degrees of clockwise turning over 40 minutes. This idealized scenario demonstrates the generalized actuator disk (GAD) implementation in FastEddy (*Sanchez Gomez et al., 2024*), with the inclusion of a turbine yawing capability to align with the meteorological wind direction at the turbine's nacelle. The initial and boundary conditions for this idealized case are derived from a horizontally averaged LES run of a neutral ABL with a geostrophic wind aligned in the zonal direction (:math:`[U_g,V_g]=[10.0,0.0]` m/s) with and a latitude of :math:`40.0^{\circ}` N. The required datasets to run this tutorial are provided at this Zenodo record [TO BE UPDATED].

The GAD model is activated by the selector (:code:`GADSelector = 1`) in the parameters file. This case uses the parameters file **tutorials/examples/Example09_GAD.in**. The lines below correspond to additions to the FastEddy parameters file necessary for turbine-inclusive LES runs. These correspond to the turbine specification file (:code:`turbineSpecsFile`) and a parameter to choose whether or not to write GAD forces to output files (:code:`GADoutputForces`).

.. code-block:: none

#--GAD
GADSelector = 1
turbineSpecsFile = ./GAD_NREL28_9WTs_tutorial.nc
GADoutputForces = 1

A key aspect required for the GAD model to work is the specification of the aerodynamic characteristics of the simulated turbine. The turbine specifications file is a netCDF formatted file that provides the aerodynamic characteristics alongside the geometric characteristics of the wind turbine (rotor diameter: :code:`GAD_rotorD`, turbine hub height: :code:`GAD_hubHeights`, nacelle diameter: :code:`GAD_nacelleD`). The turbine specifications file also informs the location and initial orientation of the turbines (:code:`GAD_Xcoords`, :code:`GAD_Ycoords`, :code:`GAD_rotorTheta`). Aerodynamic characteristics are given as polynomial fits for lift and drag coefficient, twist, chord length, blade pitch, and rotational speed discretized over a finite number of normalized blade elements (:code:`rnorm_vect`), following the blade-element momentum theory used in the GAD formulation. For flexibility purposes, an arbitrary number of turbines (:code:`GAD_turbineType`) can be defined. This tutorial provides an example turbine specification file corresponding to the U.S. Department of Energy NREL28 turbine (**GAD_NREL28_9WTs_tutorial.nc**). All the required variables and dimensions in the turbine specifications file are listed here below.

.. code-block:: none

float GAD_Xcoords(GADNumTurbines) ;
float GAD_Ycoords(GADNumTurbines) ;
float GAD_rotorTheta(GADNumTurbines) ;
int GAD_turbineType(GADNumTurbines) ;
int GADNumTurbineTypes(GADNumTurbineTypes) ;
int turbinePolyClCdrNormBounds(turbinePolyClCdrNormBounds) ;
int turbinePolyClCdrNormSegments(turbinePolyClCdrNormSegments) ;
int alphaBounds(alphaBounds) ;
int turbinePolyOrderMax(turbinePolyOrderMax) ;
float GAD_hubHeights(GADNumTurbineTypes) ;
float GAD_rotorD(GADNumTurbineTypes) ;
float GAD_nacelleD(GADNumTurbineTypes) ;
float rnorm_vect(GADNumTurbineTypes, turbinePolyClCdrNormBounds) ;
float alpha_minmax_vect(GADNumTurbineTypes, alphaBounds) ;
float turbinePolyTwist(GADNumTurbineTypes, turbinePolyOrderMax) ;
float turbinePolyChord(GADNumTurbineTypes, turbinePolyOrderMax) ;
float turbinePolyPitch(GADNumTurbineTypes, turbinePolyOrderMax) ;
float turbinePolyOmega(GADNumTurbineTypes, turbinePolyOrderMax) ;
float turbinePolyCl(GADNumTurbineTypes, turbinePolyClCdrNormSegments, turbinePolyOrderMax) ;
float turbinePolyCd(GADNumTurbineTypes, turbinePolyClCdrNormSegments, turbinePolyOrderMax) ;
int turbinePolyTwistOrder(GADNumTurbineTypes) ;
int turbinePolyChordOrder(GADNumTurbineTypes) ;
int turbinePolyPitchOrder(GADNumTurbineTypes) ;
int turbinePolyOmegaOrder(GADNumTurbineTypes) ;
int turbinePolyClOrder(GADNumTurbineTypes) ;
int turbinePolyCdOrder(GADNumTurbineTypes) ;

The GAD turbine model capability has been implemented into FastEddy as an extension module, and is not compiled by default. The user needs to build FastEddy using the following compile flag below in order to include the GAD module:

.. code-block:: none

make WITH_GAD=1

The figure shows instantaneous contours of hub height (90 m) wind speed (in m/s) spatial distribution at three different times, showcasing the yawing of the turbines to align with the time-varying wind direction throughout the course of the simulation as it shifts from SW to NW. The gray areas represent the location over which GAD forces are applied (larger than the actual rotor area).

.. image:: ../images/GAD_tutorial.png
:width: 1200
:alt: Alternative text

.. note::

* The orientation of the turbine (:code:`GAD_rotorTheta`) is defined as the angle from the negative x axis, increasing counterclockwise. This is different from the meteorological convention for wind direction. For example, a turbine facing the west will have :code:`GAD_rotorTheta` = :math:`0.0^{\circ}`, while a turbine facing south will have :code:`GAD_rotorTheta` = :math:`90.0^{\circ}`.
* Application of the GAD to a real world WRF-coupled simulation does not require any additional steps besides the ones described here.

Full citation references can be found in the :doc:`Publications <../../publications>` section.
36 changes: 36 additions & 0 deletions docs/Tutorials/cases_extensions/WRF_coupling_case0_FE_urban.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
========================================================
Real-world downscaled FastEddy simulation with buildings
========================================================

This tutorial involves setting up a real-world downscaled simulation that includes resolved buildings and closely follows the same procedure outlined in section 4.1. Additional steps for including buildings are described below and all required input datasets to run this tutorial are provided in this Zenodo record [TO BE UPDATED].

In the *GeoSpec* preprocessing step, and additional 2d field describing building heights above ground level is required in the georeference input NetCDF file.

.. code-block:: none

float BuildingHeights(y, x) ;

This tutorial provides an example georeference input file with building heights for downtown Dallas, TX (:code:`Dallas_input_Oct2025_lod13.nc`). The *geospec.json* parameter file option :code:`urban_opt : 1` needs to be selected for building height information to be ingested in the reference standard-format NetCDF output file upon execution of **GeoSpec.py**.

The same :code:`urban_opt : 1` option needs must be included in the subsequent *SimGrid* and *GenICBCs* stages, where building information is used for the creation of a :code:`BuildingMask` array containing gridded information of building presence, and ensuring that winds, subgrid-scale TKE and hydrometeors are set to zero within buildings for both initial and boundary conditions.

After initial and boundary conditions have been created, a building-resolving FastEddy simulation can be undertaken by activating the urban model capability in the parameters file (see **tutorials/examples/Example10_REALCASE_Dallas_urban.in**).

.. code-block:: none

#--URBAN
urbanSelector = 1 # urban selector: 0=off, 1=on

The urban model capability has been implemented into FastEddy as an extension module, and is not compiled by default. To include the URBAN module in a build of FastEddy use the following compile flag:

.. code-block:: none

make WITH_URBAN=1

The model used to represent buildings follows the immersed body force approach described in *Muñoz-Esparza et al., 2020*, and the tutorial case corresponds to the passage of a cold front (*Muñoz-Esparza et al. (2021, 2025)*. The figure below shows instantaneous wind speed and vertical velocity fields corresponding to 30min hindcast valid at 1500 UTC on November 11th 2011 (pre-frontal conditions). These horizontal contours are from the model's third vertical level, located at approximately 23 m above ground level.

.. image:: ../images/URBAN_tutorial_nz2_2panel.png
:width: 900
:alt: Alternative text

Full citation references can be found in the :doc:`Publications <../../publications>` section.
8 changes: 4 additions & 4 deletions docs/Tutorials/cases_real.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
***************
Real Test Cases
***************
**********
Real Cases
**********

Real cases are performed by dynamically downscaling from a mesoscale model such as WRF that can provide initial and boundary conditions for a one-way nested FastEddy simulation. These mesoscale-LES coupled simulations require the following preprocessing steps:

* Step 1: **GeoSpec**. Georeference specification step. Expects a NetCDF-formatted file of location-specific, georeferenceed coordinate frame (lat/lon), projected Cartesian coordinate frame (x,y), elevation and land cover to establish a new NetCDF file of reference geolocated domain static characteristics specification including mapping of land cover category to roughness length.
* Step 2: **SimGrid**. Simulation grid definition step. Defines a FastEddy gridded domain at a specificed grid spacing, location and extent using the file resulting from ther previous GeoSpec step and a FastEddy input parameters file (with targeted domain configuration parameters) as inputs.
* Step 3: **GenICBCs**. Generate initial conditions/boundary (ICBCs) conditions step. Creates ICBCs for a targeted FastEddy domain (defined in the SimGrid step) from a set of mesoscale model results.

The following tutorial provides a practical example of performing these preprocessing steps followed by a corresponding weather-driven FastEddy simulation for a real-world downscaled scenario.
The following tutorial provides a practical example of performing these preprocessing steps followed by a corresponding weather-driven FastEddy simulation for a real-world downscaled scenario.

.. toctree::

Expand Down
6 changes: 3 additions & 3 deletions docs/Tutorials/cases_real/WRF_coupling_case0_FE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
========================================================
Running a real-world downscaled simulation with FastEddy
========================================================
===================================================
Running a real-world downscaled FastEddy simulation
===================================================

After initial and boundary conditions have been created, a FastEddy simulation can undertaken with intial and boundary forcing from the mesoscale prognostic state fields. The lines below correspond to additions and modifications to the FastEddy parameters file necessary for coupled mesoscale-LES runs (corresponding to the test case from **tutorials/examples/Example08_REALCASE_FortCollins.in**)

Expand Down
Binary file added docs/Tutorials/images/GAD_tutorial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/Tutorials/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Tutorials

getting_started
cases
sensitivity
cases_real
cases_extensions


2 changes: 2 additions & 0 deletions docs/Tutorials/sensitivity.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
:orphan:

*************************
Sensitivity Tests (Ideal)
*************************
Expand Down
8 changes: 4 additions & 4 deletions docs/csv/extensions_gad.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
**turbineSpecsFile:** |br| The path+filename to a turbine specifications file |br| *C-O if GADSelector > 0*, N/A, N/A, , C-O
**GADoutputForces:** |br| Flag to include GAD forces in the output: |br| 0=off; 1=on |br| *C-O if GADSelector > 0*, 0, 1, 0, C-O
**GADofflineForces:** |br| Flag to compute GAD forces in an offline mode: |br| 0=off; 1=on |br| *C-O if GADSelector > 0*, 0, 1, 0, C-O
**GADaxialInduction:** |br| Flag to compute axial induction factor: |br| 0=off (uses prescribed GADaxialIndVal) |br| 1=on |br| *C-O if GADSelector > 0*, 0, 1, 0, C-O
**GADaxialIndVal:** |br| Prescribed constant axial induction factor when GADaxialInduction==1 |br| *C-O if GADSelector > 0*, 0.0, 1.0, 0.02, C-O
**GADaxialInduction:** |br| Flag to compute axial induction factor: |br| 0=off (uses prescribed GADaxialIndVal) |br| 1=on |br| *C-O if GADSelector > 0*, 0, 1, 1, C-O
**GADaxialIndVal:** |br| Prescribed constant axial induction factor when GADaxialInduction==0 |br| *C-O if GADSelector > 0*, 0.0, 1.0, 0.02, C-O
**GADrefSwitch:** |br| Switch to use reference windspeed: |br| 0=off; 1=on |br| *C-O if GADSelector > 0*, 0, 1, 0, C-O
**GADrefU:** |br| Prescribed constant reference hub-height windspeed |br| *C-M if GADSelector > 0 and* |br| *GADrefSwitch == 1*, 0.0, 50.0, 0.0, C-M
**GADrefSampleWindow:** |br| Sample duration over which to average per-timestep values (filtering out highest frequencies) |br| *C-O if GADSelector > 0*, 1.0, 60.0, 10.0, C-O
**GADrefSeriesLength:** |br| Number of sampling windows over which to average again for reference velocity magnitude and direction |br| *C-O if GADSelector > 0*, 1, 360, 30, C-O
**GADrefSampleWindow:** |br| Sample duration (in seconds) over which to average per-timestep values (filtering out highest frequencies) |br| *C-O if GADSelector > 0*, 1.0, 300.0, 30.0, C-O
**GADrefSeriesLength:** |br| Number of sampling windows over which to average again for reference velocity magnitude and direction |br| *C-O if GADSelector > 0*, 1, 360, 10, C-O
**GADForcingSwitch:** |br| Switch to use the GADrefU-based or local windspeed in computing GAD forces: |br| 0=local |br| 1=ref |br| *C-O if GADSelector > 0*, 0, 1, 0, C-O
2 changes: 1 addition & 1 deletion tutorials/examples/Example01_NBL.in
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ surflayer_z0 = 0.1 # roughness length (momentum) when surflayerSelector > 0
surflayer_z0t = 0.01 # roughness length (temperature) when surflayerSelector > 0
surflayer_wth = 0.0 # kinematic sensible heat flux at the surface when surflayerSelector = 1
surflayer_tr = -0.0 # temperature rate at the surface when surflayerSelector = 2 (>0 for warming; <0 for cooling)
surflayer_wq = 0.0 # 0.000052 # sensible heat flux at the surface (kg/kg m s-1) when surflayerSelector = 1
surflayer_wq = 0.0 # latent heat flux at the surface (kg/kg m s-1) when surflayerSelector = 1
surflayer_qr = 0.0 # water vapor rate (kg/kg h-1) when surflayerSelector = 2
surflayer_idealsine = 0 # selector for idealized sinusoidal surface heat flux or skin temperature forcing
surflayer_ideal_ts = 0.0 # start time in seconds for the idealized sinusoidal surface forcing
Expand Down
2 changes: 1 addition & 1 deletion tutorials/examples/Example02_CBL.in
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ surflayer_z0 = 0.05 # roughness length (momentum) when surflayerSelector > 0
surflayer_z0t = 0.05 # roughness length (temperature) when surflayerSelector > 0
surflayer_wth = 0.35 # kinematic sensible heat flux at the surface when surflayerSelector = 1
surflayer_tr = -0.0 # temperature rate at the surface when surflayerSelector = 2 (>0 for warming; <0 for cooling)
surflayer_wq = 0.0 # 0.000052 # sensible heat flux at the surface (kg/kg m s-1) when surflayerSelector = 1
surflayer_wq = 0.0 # latent heat flux at the surface (kg/kg m s-1) when surflayerSelector = 1
surflayer_qr = 0.0 # water vapor rate (kg/kg h-1) when surflayerSelector = 2
surflayer_idealsine = 0 # selector for idealized sinusoidal surface heat flux or skin temperature forcing
surflayer_ideal_ts = 0.0 # start time in seconds for the idealized sinusoidal surface forcing
Expand Down
Loading