Skip to content

Commit ceca9c7

Browse files
authored
Merge pull request #3225 from deslaughter/user_defined_wind_docs
Add User-defined wind documentation for InflowWind
2 parents d0cc13d + f620aec commit ceca9c7

10 files changed

Lines changed: 773 additions & 12 deletions

File tree

docs/source/user/inflowwind/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ InflowWind Users Guide and Theory Manual
1919

2020
driver.rst
2121
input.rst
22+
user_defined.rst
2223
appendix.rst
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
.. _ifw_user_defined:
2+
3+
User-Defined Wind Fields
4+
=========================
5+
6+
This section explains how to implement custom wind fields in InflowWind using ``WindType = 6``.
7+
8+
Overview
9+
--------
10+
11+
The user-defined wind field feature allows developers to implement custom wind models by:
12+
13+
1. Defining a data structure to hold wind field parameters
14+
2. Initializing that data structure from input files or parameters
15+
3. Implementing a function to return wind velocities at any position and time
16+
17+
This is useful for:
18+
19+
- Analytical wind models (e.g., vortex, wake models)
20+
- Custom wind profiles not available in standard formats
21+
- Coupling to external wind solvers
22+
- Real-time wind measurements from sensors
23+
- Research and development of new wind field representations
24+
25+
.. important::
26+
After modifying the registry files (``.txt`` files), you must rebuild the project
27+
to regenerate the type definition files (``*_Types.f90``). The modifications to the
28+
``.txt`` files define the extended data structures, but they won't be available
29+
until after regeneration.
30+
31+
Implementation Steps
32+
--------------------
33+
34+
Step 1: Define Data Structure
35+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
36+
37+
Edit ``modules/inflowwind/src/IfW_FlowField.txt`` and add fields to ``UserFieldType``:
38+
39+
.. code-block:: text
40+
41+
typedef ^ UserFieldType ReKi RefHeight - - - "reference height; used to center the wind" meters
42+
typedef ^ ^ IntKi NumDataLines - 0 - "number of data lines (for time-varying user wind)" -
43+
typedef ^ ^ DbKi DTime : - - "time array for user-defined wind" seconds
44+
typedef ^ ^ ReKi Data :: - - "user-defined wind data array [NumDataLines, NumDataColumns]" -
45+
typedef ^ ^ CHARACTER(1024) FileName - - - "name of user wind file (if applicable)" -
46+
47+
Add any custom fields needed for your wind model implementation.
48+
49+
Step 2: Define Initialization Inputs
50+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51+
52+
Edit ``modules/inflowwind/src/InflowWind_IO.txt`` and add fields to ``User_InitInputType``:
53+
54+
.. code-block:: text
55+
56+
typedef ^ User_InitInputType CHARACTER(1024) WindFileName - - - "name of file containing user-defined wind data (if applicable)" -
57+
typedef ^ ^ ReKi RefHt - - - "reference height for user wind field" meters
58+
typedef ^ ^ IntKi NumDataColumns - 0 - "number of data columns in user wind file (if applicable)" -
59+
60+
Add any parameters needed to initialize your wind model.
61+
62+
Step 3: Regenerate Type Files
63+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
64+
65+
After modifying the registry files, rebuild the project to regenerate type definitions. When using Visual Studio
66+
to build OpenFAST on Windows, the types files are automatically regenerated. When using CMake,
67+
run the following commands to enable generation of the types files.
68+
69+
.. code-block:: bash
70+
71+
cd build
72+
cmake .. -DGENERATE_TYPES=ON
73+
make
74+
75+
The build process automatically regenerates the ``*_Types.f90`` files from the ``.txt`` registry files.
76+
77+
Step 4: Implement Initialization
78+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79+
80+
Edit ``modules/inflowwind/src/InflowWind_IO.f90`` and implement ``IfW_User_Init()``:
81+
82+
.. code-block:: fortran
83+
84+
subroutine IfW_User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg)
85+
! Initialize UF%RefHeight, read data files, allocate arrays
86+
! Set FileDat metadata (wind type, time range, spatial extent, etc.)
87+
! Write summary information to SumFileUnit if > 0
88+
end subroutine
89+
90+
This routine:
91+
92+
- Reads any necessary input files specified in ``InitInp``
93+
- Allocates and populates the ``UserFieldType`` (``UF``) data structure
94+
- Sets appropriate metadata in the ``WindFileDat`` structure
95+
- Writes initialization information to the summary file
96+
97+
Step 5: Implement Velocity Function
98+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99+
100+
Edit ``modules/inflowwind/src/IfW_FlowField.f90`` and implement ``UserField_GetVel()``:
101+
102+
.. code-block:: fortran
103+
104+
subroutine UserField_GetVel(UF, Time, Position, Velocity, ErrStat, ErrMsg)
105+
! Use UF data to compute velocity at Position and Time
106+
! Position(1) = X, Position(2) = Y, Position(3) = Z (meters)
107+
! Return Velocity(1) = U, Velocity(2) = V, Velocity(3) = W (m/s)
108+
end subroutine
109+
110+
This function is called for each position where wind velocities are needed during simulation.
111+
112+
Coordinate Systems
113+
------------------
114+
115+
Input Coordinates (Position)
116+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
117+
118+
- **X**: Downstream direction (after rotation applied by InflowWind)
119+
- **Y**: Lateral/crosswind direction
120+
- **Z**: Vertical direction (measured from ground, Z=0 is ground level)
121+
- **Units**: meters
122+
123+
Output Velocities (Velocity)
124+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125+
126+
- **U**: Velocity component along X (positive = downwind)
127+
- **V**: Velocity component along Y (positive = to the left when looking downwind)
128+
- **W**: Velocity component along Z (positive = upward)
129+
- **Units**: m/s
130+
131+
.. note::
132+
InflowWind handles the rotation between global coordinates and wind coordinates.
133+
Your implementation should work in the wind coordinate system where X is aligned
134+
with the mean wind direction.
135+
136+
Example Implementation
137+
----------------------
138+
139+
Power-Law Wind Profile
140+
~~~~~~~~~~~~~~~~~~~~~~
141+
142+
This example implements a simple power-law wind profile.
143+
144+
**Velocity Function** (in ``IfW_FlowField.f90``):
145+
146+
.. code-block:: fortran
147+
148+
subroutine UserField_GetVel(UF, Time, Position, Velocity, ErrStat, ErrMsg)
149+
type(UserFieldType), intent(in) :: UF
150+
real(DbKi), intent(in) :: Time
151+
real(ReKi), intent(in) :: Position(3)
152+
real(ReKi), intent(out) :: Velocity(3)
153+
integer(IntKi), intent(out) :: ErrStat
154+
character(*), intent(out) :: ErrMsg
155+
156+
real(ReKi) :: RefSpeed, Exponent, Height
157+
158+
ErrStat = ErrID_None
159+
ErrMsg = ""
160+
161+
! Get reference speed and exponent from UF%Data
162+
RefSpeed = UF%Data(1, 1) ! Reference wind speed (m/s)
163+
Exponent = UF%Data(1, 2) ! Power law exponent
164+
Height = Position(3) ! Height above ground
165+
166+
! Apply power law: U(z) = Uref * (z/zref)^alpha
167+
if (Height > 0.0_ReKi) then
168+
Velocity(1) = RefSpeed * (Height / UF%RefHeight)**Exponent
169+
Velocity(2) = 0.0_ReKi ! No lateral wind
170+
Velocity(3) = 0.0_ReKi ! No vertical wind
171+
else
172+
Velocity = 0.0_ReKi ! Below ground
173+
end if
174+
175+
end subroutine
176+
177+
**Initialization** (in ``InflowWind_IO.f90``):
178+
179+
.. code-block:: fortran
180+
181+
subroutine IfW_User_Init(InitInp, SumFileUnit, UF, FileDat, ErrStat, ErrMsg)
182+
! ... (declarations)
183+
184+
ErrStat = ErrID_None
185+
ErrMsg = ""
186+
187+
! Set reference height
188+
UF%RefHeight = InitInp%RefHt
189+
190+
! Allocate data array for [RefSpeed, Exponent]
191+
UF%NumDataLines = 1
192+
call AllocAry(UF%Data, 1, 2, 'User wind data', TmpErrStat, TmpErrMsg)
193+
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
194+
if (ErrStat >= AbortErrLev) return
195+
196+
! Set values (could read from file instead)
197+
UF%Data(1, 1) = 10.0_ReKi ! 10 m/s reference speed
198+
UF%Data(1, 2) = 0.2_ReKi ! Power law exponent
199+
200+
! Set metadata
201+
FileDat%WindType = 6
202+
FileDat%RefHt = UF%RefHeight
203+
FileDat%MWS = UF%Data(1, 1)
204+
FileDat%RefHt_Set = .true.
205+
! ... (set other FileDat fields as needed)
206+
207+
end subroutine
208+
209+
Common Use Cases
210+
----------------
211+
212+
Steady Analytical Wind Field
213+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
214+
215+
Define wind as a function of position only (ignore ``Time`` parameter).
216+
217+
**Example**: Logarithmic wind profile, vortex wind field, uniform flow with shear.
218+
219+
Time-Varying Wind Field
220+
~~~~~~~~~~~~~~~~~~~~~~~
221+
222+
Store wind data in time series arrays and interpolate based on ``Time`` parameter.
223+
224+
**Example**: Measured wind data, prescribed wind transients, wake models.
225+
226+
Wind from External Solver
227+
~~~~~~~~~~~~~~~~~~~~~~~~~~
228+
229+
Call external functions to get instantaneous wind fields.
230+
231+
**Example**: CFD coupling, external wake models, prescribed turbulence.
232+
233+
Real-Time Sensor Data
234+
~~~~~~~~~~~~~~~~~~~~~
235+
236+
Load measured wind data from sensors and interpolate spatially/temporally.
237+
238+
**Example**: LIDAR measurements, met mast data, field measurements.
239+
240+
Limitations and Considerations
241+
-------------------------------
242+
243+
Current Limitations
244+
~~~~~~~~~~~~~~~~~~~
245+
246+
1. **No Acceleration Support**: User-defined wind fields do not currently support
247+
acceleration calculations needed by some modules (e.g., MHK turbines).
248+
249+
Performance Considerations
250+
~~~~~~~~~~~~~~~~~~~~~~~~~~
251+
252+
- ``UserField_GetVel()`` is called for every point at every time step
253+
- Implement efficiently; pre-compute values in ``IfW_User_Init()`` when possible
254+
- Consider caching or interpolation strategies for complex calculations
255+
256+
Error Handling
257+
~~~~~~~~~~~~~~
258+
259+
- Always validate input parameters in ``IfW_User_Init()``
260+
- Check array bounds in ``UserField_GetVel()``
261+
- Verify Position and Time values are within valid ranges
262+
- Use ``SetErrStat()`` to report errors appropriately
263+
264+
Best Practices
265+
--------------
266+
267+
1. **Start Simple**: Begin with analytical models before implementing complex wind fields
268+
269+
2. **Document Thoroughly**: Add detailed comments explaining your implementation and any file formats
270+
271+
3. **Use SI Units**: Always use meters, seconds, and m/s
272+
273+
4. **Pre-compute**: Calculate as much as possible during initialization rather than runtime
274+
275+
5. **Validate**: Test with known analytical solutions before using in production
276+
277+
6. **Handle Boundaries**: Implement appropriate behavior for points outside valid domain
278+
279+
7. **Report Metadata**: Properly populate ``WindFileDat`` with time range, spatial extent, etc.
280+
281+
File Locations
282+
--------------
283+
284+
========================================== ==========================================================
285+
File Purpose
286+
========================================== ==========================================================
287+
``modules/inflowwind/src/`` Source code directory
288+
``IfW_FlowField.txt`` Type definitions for flow field data structures
289+
``InflowWind_IO.txt`` Type definitions for initialization inputs
290+
``IfW_FlowField.f90`` Flow field implementation (``UserField_GetVel()``)
291+
``InflowWind_IO.f90`` Initialization implementation (``IfW_User_Init()``)
292+
``IfW_FlowField_Types.f90`` Auto-generated type definitions (regenerated from .txt)
293+
``InflowWind_IO_Types.f90`` Auto-generated type definitions (regenerated from .txt)
294+
========================================== ==========================================================
295+
296+
Additional Resources
297+
--------------------
298+
299+
- See the original :download:`InflowWind Manual <InflowWind_Manual.pdf>` for general InflowWind information
300+
- Review existing wind field implementations (Uniform, Grid3D) in the source code for reference
301+
- Check :ref:`ifw_appendix` for example input files
302+
- Refer to NWTC Library documentation for array allocation and error handling utilities
303+
- See :ref:`ifw_angles` for information about wind coordinate systems and rotations

0 commit comments

Comments
 (0)