Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • toolbox/WindEnergyToolbox
  • tlbl/WindEnergyToolbox
  • cpav/WindEnergyToolbox
  • frza/WindEnergyToolbox
  • borg/WindEnergyToolbox
  • mmpe/WindEnergyToolbox
  • ozgo/WindEnergyToolbox
  • dave/WindEnergyToolbox
  • mmir/WindEnergyToolbox
  • wluo/WindEnergyToolbox
  • welad/WindEnergyToolbox
  • chpav/WindEnergyToolbox
  • rink/WindEnergyToolbox
  • shfe/WindEnergyToolbox
  • shfe1/WindEnergyToolbox
  • acdi/WindEnergyToolbox
  • angl/WindEnergyToolbox
  • wliang/WindEnergyToolbox
  • mimc/WindEnergyToolbox
  • wtlib/WindEnergyToolbox
  • cmos/WindEnergyToolbox
  • fabpi/WindEnergyToolbox
22 results
Select Git revision
Show changes
Showing
with 6503 additions and 195 deletions
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.join(os.path.abspath('.'), '..', '..'))
from wetb import __version__
# -- Project information -----------------------------------------------------
project = 'WETB'
copyright = '2018, DTU Wind Energy'
author = 'DTU Wind Energy'
# The short X.Y version
version = __version__
# The full version, including alpha/beta/rc tags
release = __version__
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.autosummary',
'sphinx.ext.napoleon',
'sphinx.ext.viewcode',
'nbsphinx',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
# TOC options
#'navigation_depth': 2, # only show 2 levels on left sidebar
'collapse_navigation': False, # don't allow sidebar to collapse
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# The default sidebars (for documents that don't match any pattern) are
# defined by theme itself. Builtin themes are using these templates by
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
# 'searchbox.html']``.
#
# html_sidebars = {}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'WETBdoc'
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
#(master_doc, 'PyWake.tex', 'PyWake Documentation', 'DTU Wind Energy', 'manual'),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'wetb', 'WETB Documentation',
[author], 1)
]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'WETB', 'WETB Documentation',
author, 'WETB', 'Wind Energy Toolbox.',
'Miscellaneous'),
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# -- Extension configuration -------------------------------------------------
......@@ -58,63 +58,51 @@ is a gui integrated into the windows explorer.
## Install Python
For all platforms we recommend that you download and install the Anaconda -
a professional grade, full blown scientific Python distribution.
### Installing Anaconda, activate root environment
* Download and install Anaconda (Python 3.5 version, 64 bit installer is
recommended) from <https://www.continuum.io/downloads>
### Installing Miniconda
> Note: The Python 2.7 or Python 3.5 choice of Anaconda only affects the
root environment. You can always create additional environments using other
Python versions, see below.
* Download and install Anaconda (Python 3.8 version, 64 bit installer is
recommended) from <https://docs.conda.io/en/latest/miniconda.html>.
* Update the root Anaconda environment (type in a terminal):
You should now be able to find a `Anaconda Powershell (Miniconda)` or
`Anaconda Prompt (Miniconda)` application launcher. This will drop you in a
terminal alike application, saying something like this:
```
>> conda update --all
(base) C:\Users\>
```
* Activate the Anaconda root environment in a terminal as follows:
and where `(base)` refers to your base Miniconda installation environment.
You can keep the base environment updated as follows (type in a terminal):
```
>> activate
```
and your terminal will do something like:
```
C:\Users\> activate
(root) C:\Users\>
>> conda update --all
```
note that the name of the environment is now a prefix before the current path.
use ```deactivate``` to deactivate the environment.
### Optionally, create other independent Anaconda environments
By using environments you can manage different Python installations with
different versions on your system. Creating environments is as easy as:
different versions on your system independently. Creating environments is as easy as:
```
>> conda create -n py27 python=2.7
>> conda create -n py34 python=3.4
>> conda create -n py35 python=3.5
>> conda create -n py39 python=3.9
```
These environments can be activated as follows:
Where `-n py39` refers any user defined name that describes what is the environment
used for. These environments can then be activated as follows:
```
>> activate py27
>> activate py34
>> activate py35
>> conda activate py39
```
The Python distribution in use will now be located in e.g. \<path_to_anaconda\>/env/py35/
The Python distribution in use will now be located in e.g. \<path_to_anaconda\>/env/py39/
use ```deactivate``` to deactivate the environment.
use ```conda deactivate``` to deactivate the environment.
## Install/build dependencies
......@@ -122,12 +110,11 @@ use ```deactivate``` to deactivate the environment.
- Compiler (```wetb``` contains cython extensions that require a compiler):
- Linux: gcc (should be installed by default)
- Windows:
- Python 2.7: [Microsoft Visual C++ Compiler for Python 2.7](http://aka.ms/vcpython27),
or the [direct link](https://www.microsoft.com/en-gb/download/details.aspx?id=44266).
- Python 3.4: MS Visual Studio 2010
- Python 3.5: MS Visual Studio 2015 or [Visual C++ Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools)
- Python 3.5+: MS Visual Studio 2022 or [Visual C++ 2022 Redistributable](https://visualstudio.microsoft.com/downloads/#microsoft-visual-c-redistributable-for-visual-studio-2022)
https://visualstudio.microsoft.com/visual-cpp-build-tools/
- Only one MS Visual Studio version can be installed, but you can for
example install MS Visual Studio 2010 alongside the Visual C++ Build Tools.
example install MS Visual Studio 2022 alongside different Visual C++ Build Tools.
- [numpy](http://www.numpy.org/)
- [cython](http://cython.org/)
- [scipy](http://scipy.org/scipylib/)
......@@ -137,28 +124,25 @@ use ```deactivate``` to deactivate the environment.
- [h5py](http://www.h5py.org/)
- [matplotlib](http://matplotlib.org/)
- [pytables](http://www.pytables.org/)
- [pyscaffold](http://pyscaffold.readthedocs.org/en/)
- [pytest](https://pypi.python.org/pypi/pytest)
- [pytest-cov](https://pypi.python.org/pypi/pytest-cov/)
- six, [future](http://python-future.org/index.html)
- nose, sphinx, blosc, pbr, psutil, coverage, setuptools_scm
- [parimeko](http://www.paramiko.org/)
- nose, sphinx, blosc, pbr, psutil, coverage, six
- [paramiko](http://www.paramiko.org/)
- [sshtunnel](https://github.com/pahaz/sshtunnel)
- [pandoc](http://pandoc.org/) , [pypandoc](https://pypi.python.org/pypi/pypandoc):
- [click](https://click.palletsprojects.com/en/7.x/)
- [jinja2](https://jinja.palletsprojects.com/en/2.10.x/)
convert markdown formatted readme file to rst for PyPi compatibility. See also
issue #22. ```pandoc``` is available in Anaconda. When installing
```pypandoc``` via pip, you have to install ```pandoc``` via your package
manager (Linux/Mac).
- [twine](https://pypi.python.org/pypi/twine): upload package to
[PyPi](https://pypi.python.org/pypi)
Install the necessary Python dependencies using the conda package manager:
```
>> conda install setuptools_scm future h5py pytables pytest pytest-cov nose sphinx blosc pbr paramiko
>> conda install scipy pandas matplotlib cython xlrd coverage xlwt openpyxl psutil pandoc
>> conda install -c conda-forge pyscaffold pypandoc sshtunnel --no-deps
>> conda install --channel https://conda.anaconda.org/pbrod twine --no-deps
conda install mock h5py pytables pytest pytest-cov nose sphinx blosc pbr paramiko
conda install scipy pandas matplotlib cython coverage openpyxl psutil click jinja2
conda install -c conda-forge sshtunnel --no-deps
```
Note that ```--no-deps``` avoids that newer packages from the channel
......@@ -195,6 +179,43 @@ above for the ```conda-forge``` channel: it is to avoid that pip will replace
newer packages compared to the ones as available in the ```Anaconda``` channel.
## Update wetb
```
>> cd WindEnergyToolbox
>> git pull
>> pip install -e . --no-deps
```
## Run tests
Note that the test should be executed from a clean repository and which is not
used as a development installation with ```pip install -e .```. For example,
create a clone of your local git repository in which your development takes
place, but name the top level folder to something else:
```
>> git clone WindEnergyToolbox/ wetb_tests
>> cd wetb_tests
```
In order to make sure your git repository is clean, this will remove all
untracked files, and undo all untracked changes. WARNING: you will loose all
untracked files and changes!!
```
>> git clean -df & git checkout .
```
Now we have clean repository that is not used as a development installation
directory, and we simply track our own local development git repository.
Use ```git pull``` to get the latest local commits.
```
>> python -m pytest --cov=wetb
```
## Contributions
If you make a change in the toolbox, that others can benefit from please make a merge request.
......@@ -219,6 +240,14 @@ To be written
## Make and upload wheels to PyPi
### Linux
For Linux the wheels are now automatically build and pushed to pypi when creating a tag.
### Windows
For Windows the automated build and push to pypi has not yet been implemented and the developer has to follow the manual procedure outlined below:
Workflow for creating and uploading wheels is as follows:
- Make tag: ```git tag "vX.Y.Z"```, and push tag to remote: ```git push --tags```
......@@ -240,4 +269,3 @@ In case of problems:
will fail. This means commit hashes can not be part of the version number.
Note that when your git working directory is not clean, the scheme for automatic
versioning number will add ```dirty``` to the version number.
Fatigue tools
===========================
``wetb`` includes functions to help with the calculation of fatigue
equivalent loads for turbines. The documentation is in a Jupyter
notebook format. You can download the source notebook from the
``wetb`` repository, under ``docs/source/fatigue_tools``.
.. toctree::
:caption: Fatigue tools
:maxdepth: 2
notebooks/Fatigue
\ No newline at end of file
......@@ -14,10 +14,10 @@ This tool comes handy in the following scenarios:
* different parameters variations are required, e.g. different wind speed range or different number of turbulent seed.
The generator of the cases uses an input spreadsheet where the cases are defined
in a more compact way.
The tool is based on the "tags" concept that is used for the genetaion of the htc files.
in a more compact way.
The tool is based on the "tags" concept that is used for the generation of the htc files.
Main spreatsheet
Main spreadsheet
----------------
A main spreadsheet is used to defines all the DLC of the DLB. The file specifies the tags that are then required in the htc files.
......@@ -26,22 +26,47 @@ The file has:
* a Main sheet where some wind turbines parameters are defined, the tags are initialized, and the definitions of turbulence and gusts are given.
* a series of other sheets, each defining a DLC. In these sheets the tags that changes in that DLC are defined.
The tags are devided into three possible different categories:
The tags are divided into three possible different categories:
* Constants (C). Constants are tags that do not change in a DLC, e.g. simulation time, output format, ...;
* Variables (V). Variables are tags that define the number of cases in a DLC through their combinations, e.g. wind speed, number of turbilence seeds, wind direction, ..;
* Variables (V). Variables are tags that define the number of cases in a DLC through their combinations, e.g. wind speed, number of turbulence seeds, wind direction, ..;
* Functions (F). Functions are tags that depend on other tags through an expression, e.g. turbulence intensity, case name, ....
In each sheet the type of tag is defined in the line above the tag by typing one of the letters C, V, or F.
Functions (F) tags
------------------
* Numbers can be converted to strings (for example when a tag refers to a file name)
by using double quotes ```"``` for Functions (F):
* ```"wdir_[wdir]deg_wsp_[wsp]ms"``` will result in the tags ``` [wdir]```
and ```[wsp]``` being replaced with formatted text.
* following formatting rules are used:
* ```[wsp]```, ```[gridgustdelay]``` : ```02i```
* ```[wdir]```, ```[G_phi0]``` : ```03i```
* ```[Hs]```, ```[Tp]``` : ```05.02f```
* all other tags: ```04i```
* Only numbers in tags with double quotes are formatted. In all other cases
there is no formatting taking place and hence no loss of precision occurs.
* In this context, when using quotes, always use double quotes like ```"```.
Do not use single quotes ```'``` or any other quote character.
Variable (V) tags
-----------------
* ```[seed]``` and ```[wave_seed]``` are special variable tags. Instead of defining
a range of seeds, the user indicates the number of seeds to be used.
* ```[wsp]``` is a required variable tag
* ```[seed]``` should be placed in a column BEFORE ```[wsp]```
Generate the files
------------------
To generate the files defining the different DLC the following lines need to be executed:
export PATH=/home/python/miniconda3/bin:$PATH
source activate wetb_py3
python /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/GenerateDLCs.py --folder=DLCs
source activate py36-wetb
python /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/GenerateDLCs.py --folder=DLCs
the first two lines activate the virtual environment. The third calls the routine *GenerateDLCs.py * that generates the files.
The routine should be called from the folder *htc* where also the master spreadsheet *DLCs.xlsx* need to be located.
The generated files are placed in the folder *DLCs*.
......@@ -61,11 +61,11 @@ do this when the turbulence box size changes (e.g., if the rotor size changes)
or if you have a model that's never been simulated on mimer.
2. Determine your set ID code. There are two scenarios:
* No one else in your project has run simulations on mimer. In this case,
create a new set ID alpha code (e.g., "AA", "AB", etc.).
create a new set ID alpha code (e.g., "AA", "AB", etc.).
* Simulations for this project/turbine configuration already exist. In this
case, use a pre-existing set ID alpha code and add one to the most recent
Set ID (e.g., if "AB0008" exists, your new folder should be "AB0009").
Set ID (e.g., if "AB0008" exists, your new folder should be "AB0009").
##### 3. Add proper log files for your Set ID folder.
See the [house rules](docs/houserules-mimerhawc2sim.md) regarding log files.
......@@ -86,7 +86,7 @@ structure similar to this:
Your master htc file, stored in ```htc/_master/```, can take any desired naming
convention, but it must have ```_master_``` in the name or future scripts will
abort. ```htc/DLCs.xlsx``` is your master Excel file that will create the
abort. ```htc/DLCs.xlsx``` is your master Excel file that will create the
subordinate Excel files in the coming steps.
##### 5. Create your subordinate Excel files.
......@@ -94,7 +94,7 @@ From a terminal, change to your htc directory. Then run the following code:
```
$ export PATH=/home/python/miniconda3/bin:$PATH
$ source activate wetb_py3
$ source activate py36-wetb
$ python /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/GenerateDLCs.py --folder=DLCs
$ source deactivate
```
......@@ -102,10 +102,7 @@ $ source deactivate
This will create a subfolders DLCs and fill that new subfolder with the created
subordinate Excel files.
##### 6. Move your DLCs.xlsx file from the htc folder to the ```_master``` folder.
It will cause errors in later scripts if left in the htc folder.
##### 7. Create your htc files and PBS job scripts .
##### 6. Create your htc files and PBS job scripts .
These files and scripts are generated from the subordinate Excel files from
Step 5. To do this, in the terminal, change up a level to your Set ID folder
(e.g., to folder "AB0001"). Then run this code
......@@ -117,7 +114,7 @@ $ qsub-wrap.py -f /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/
Your htc files should now be placed in subfolders in the htc folder, and PBS
job files should be in folder ```pbs_in```.
##### 8. Launch the htc files to the cluster.
##### 7. Launch the htc files to the cluster.
Use the ```launch.py``` function to launch the jobs on the cluster.
For example, the following code will launch the jobs in folder ```pbs_in``` on
100 nodes. You must be in the top-level Set ID folder for this to work (e.g.,
......@@ -128,7 +125,7 @@ $ launch.py -n 100 -p pbs_in/
```
There are many launch options available. You can read more about the options
and querying the cluster configurations/status/etc. on
and querying the cluster configurations/status/etc. on
[this page](docs/howto-make-dlcs.md), or you can use the ```launchy.py```
help function to print available launch options:
......@@ -136,9 +133,9 @@ help function to print available launch options:
$ launch.py --help
```
##### 9. Post-process results.
##### 8. Post-process results.
The wetb function ```qsub-wrap.py``` can not only generate htc files but also
The wetb function ```qsub-wrap.py``` can not only generate htc files but also
post-process results. For example, here is code to check the log files
and calculate the statistics, the AEP and the lifetime equivalent loads
(must be executed from the top-level Set ID folder):
......
HAWC2 tools
===========================
``wetb`` includes functions to help with the writing of HAWC2 input
files, also know as htc files. The documentation is in a Jupyter
notebook format. You can download the source notebooks from the
``wetb`` repository, under ``docs/source/hawc2``.
.. toctree::
:caption: HAWC2
notebooks/hawc2/InputFileWriting
notebooks/hawc2/RunningSimulations
notebooks/hawc2/RunningSimulationsJess
This diff is collapsed.
Welcome to WETB
===========================================
*- The Wind Energy Toolbox of DTU*
This toolbox provides Python tools intended for use in the wind
community, and especially HAWC2 users. Please see the Installation
tab on the left to install the code and get started.
Source code repository (and issue tracker):
https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox
License:
GPLv3_
.. _GPLv3: https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/LICENSE.txt
Contents:
.. toctree::
installation
fatigue
hawc2
bladed/bladed2hawc
......@@ -6,9 +6,9 @@
```
conda update --all
conda create -n wetb_py3 python=3.5
source activate wetb_py3
conda install setuptools_scm future h5py pytables pytest nose sphinx blosc psutil
conda create -n py36-wetb python=3.6
source activate py36-wetb
conda install setuptools_scm mock h5py pytables pytest nose sphinx blosc psutil
conda install scipy pandas matplotlib cython xlrd coverage xlwt openpyxl paramiko
conda install -c https://conda.anaconda.org/conda-forge pyscaffold pytest-cov
```
......@@ -17,9 +17,9 @@ conda install -c https://conda.anaconda.org/conda-forge pyscaffold pytest-cov
```
conda update --all
conda create -n wetb_py3 python=3.4
source activate wetb_py3
conda install setuptools_scm future h5py pytables pytest nose sphinx psutil
conda create -n py36-wetb python=3.6
source activate py36-wetb
conda install setuptools_scm mock h5py pytables pytest nose sphinx psutil
conda install scipy pandas matplotlib cython xlrd coverage xlwt openpyxl paramiko
conda install -c https://conda.anaconda.org/conda-forge pyscaffold pytest-cov
```
......
# Anaconda (Windows/Mac/Linux)
## Installation
......@@ -7,9 +5,9 @@
Install the necessary Python dependencies using the ```conda``` package manager:
```
>> conda install setuptools_scm future h5py pytables pytest pytest-cov nose sphinx blosc pbr paramiko
>> conda install setuptools_scm mock h5py pytables pytest pytest-cov nose sphinx blosc pbr paramiko
>> conda install scipy pandas matplotlib cython xlrd coverage xlwt openpyxl psutil
>> conda install -c conda-forge pyscaffold sshtunnel --no-deps
>> conda install -c conda-forge sshtunnel --no-deps
```
Now you can install ```wetb``` with ```pip``` (there is no ```conda``` package
......@@ -32,34 +30,12 @@ expclicitally tell ```pip``` to only install ```wetb``` and nothing more:
# Pip (Windows/Mac/Linux)
Do not use this procedure in conda environments. See above.
## Installation and update
```
>> pip install --upgrade wetb
```
# Works with Python 2 and Python 3
This module is tested for Python 2.7 and 3.4+ compatibility, and works on both
Windows and Linux. Testing for Mac is on the way, but in theory it should work.
Python 2 and 3 compatibility is achieved with a single code base with the help
of the Python module [future](http://python-future.org/index.html).
Switching to Python 3 is in general a very good idea especially since Python 3.5
was released. Some even dare to say it
[is like eating your vegetables](http://nothingbutsnark.svbtle.com/porting-to-python-3-is-like-eating-your-vegetables).
So if you are still on Python 2, we would recommend you to give Python 3 a try!
You can automatically convert your code from Python 2 to 3 using the
[2to3](https://docs.python.org/2/library/2to3.html) utility which is included
in Python 2.7 by default. You can also write code that is compatible with both
2 and 3 at the same time (you can find additional resources in
[issue 1](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/issues/1)).
# Note
This project has been set up using PyScaffold 2.5. For details and usage
information on PyScaffold see http://pyscaffold.readthedocs.org/.
.. _installation:
Installation
===========================
Normal user
--------------------------------
* Quick install::
pip install wetb
* Install a specific version on PyPI::
pip install wetb==0.0.21
* Update an installation to the most recent version::
pip install --upgrade wetb
* Install with dependencies needed by prepost
pip install wetb[prepost]
* Install with all dependencies
pip install wetb[all]
**NOTE**. Dependency conflicts can arise if you do not install
``wetb`` into a clean environment. In particular, your installation
might break if ``wetb`` is installed using ``pip``, and then later
packages are installed using ``conda``. (See more details at
`this article <https://www.anaconda.com/blog/using-pip-in-a-conda-environment>`_.
We therefore recommend that you install ``wetb`` in a clean
environment.
Advanced user
--------------------------------
Clone the repository and install a local editable copy::
git clone https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox.git
cd WindEnergyToolbox
pip install -e .[all]
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd
Source diff could not be displayed: it is too large. Options to address this: view the blob.
This diff is collapsed.
%% Cell type:markdown id: tags:
# Running simulations
%% Cell type:markdown id: tags:
## Single simulation on local pc
%% Cell type:code id: tags:
``` python
from wetb import hawc2
from wetb.hawc2 import HTCFile
from wetb.hawc2.tests.test_files import tfp
```
%% Cell type:code id: tags:
``` python
hawc2_path = "HAWC2MB.exe" # make sure HAWC2MB.exe is on your path or specify the full path to HAWC2
```
%% Cell type:markdown id: tags:
Generate and save a HAWC2 input htc file for a short simulation
%% Cell type:code id: tags:
``` python
htc = HTCFile(tfp + "simulation_setup/DTU10MWRef6.0/htc/DTU_10MW_RWT.htc")
htc.simulation.time_stop = 1 # stop the simulation after 1 s
htc.save(tfp + 'simulation_setup/DTU10MWRef6.0/htc/tmp.htc')
```
%% Cell type:markdown id: tags:
Execute the simulation
%% Cell type:code id: tags:
``` python
stdout, log = htc.simulate(hawc2_path)
```
%% Cell type:code id: tags:
``` python
print(stdout)
```
%% Output
***********************************************************************
* Build information for HAWC2MB.exe (GIT)
* Intel, version 1900 , 20190206
* WINDOWS 32-bit
***********************************************************************
* GIT-TAG = 12.8.0
* BUILDER = mmpe
* COMPUTER_NAME = VINDRI-D17205
* BUILD_DATE = 30-01-2020
***********************************************************************
Logfile: ./log/dtu_10mw_rwt_ver4.log is open for log outputs
Basic DTU Wind Energy Controller (ver. 2.3 v0.1.dev69.17400ca) loaded ...
Gen. torque Servo (ver. 2.2 v0.1.dev15.eddfec3) loaded...
Mech brake (ver. 2.2 v0.1.dev14.9e614a3) loaded...
Pitch Servo (ver. 2.2 v0.1.dev15.eddfec3) loaded...
Using licence_manager.dll, version: unknown
License verified - OK
Opening main command file: htc\tmp.htc
Current directory is
c:\mmpe\programming\python\windenergytoolbox\wetb\hawc2\tests\test_files\simula
tion_setup\DTU10MWRef6.0
Continue on no convergence = true
%% Cell type:code id: tags:
``` python
print(log)
```
%% Output
***********************************************************************
* Build information for HAWC2MB.exe (GIT)
* Intel, version 1900 , 20190206
* WINDOWS 32-bit
***********************************************************************
* GIT-TAG = 12.8.0
* BUILDER = mmpe
* COMPUTER_NAME = VINDRI-D17205
* BUILD_DATE = 30-01-2020
***********************************************************************
________________________________________________________________________________________________________________________
Log file output
Time : 14:55:07
Date : 26:05.2020
________________________________________________________________________________________________________________________
Newmark commands read with succes
Simulation commands read with succes
Reading data of main body : tower
Succes opening ./data/dtu_10mw_rwt_tower_st.dat
timoschenko input commands read with succes
topologi_c2def_inputs read with succes
Topologi main body tower commands read with succes
Reading data of main body : towertop
Succes opening ./data/dtu_10mw_rwt_towertop_st.dat
timoschenko input commands read with succes
topologi_c2def_inputs read with succes
Topologi main body towertop commands read with succes
Reading data of main body : shaft
Succes opening ./data/dtu_10mw_rwt_shaft_st.dat
timoschenko input commands read with succes
topologi_c2def_inputs read with succes
Topologi main body shaft commands read with succes
Reading data of main body : hub1
Succes opening ./data/dtu_10mw_rwt_hub_st.dat
timoschenko input commands read with succes
topologi_c2def_inputs read with succes
Topologi main body hub1 commands read with succes
Reading data of main body : hub2
Topologi main body hub2 commands read with succes
Reading data of main body : hub3
Topologi main body hub3 commands read with succes
Reading data of main body : blade1
Succes opening ./data/dtu_10mw_rwt_blade_st.dat
timoschenko input commands read with succes
topologi_c2def_inputs read with succes
Topologi main body blade1 commands read with succes
Reading data of main body : blade2
Topologi main body blade2 commands read with succes
Reading data of main body : blade3
Topologi main body blade3 commands read with succes
Base orientation input commands read with succes
relative orientation input commands read with succes
relative orientation input commands read with succes
relative orientation input commands read with succes
relative orientation input commands read with succes
relative orientation input commands read with succes
relative orientation input commands read with succes
relative orientation input commands read with succes
relative orientation input commands read with succes
Orientation input commands read with succes
Fix0 constraint input commands read with succes
Fix1 constraint input commands read with succes
Bearing1 constraint input commands read with succes
Fix1 constraint input commands read with succes
Fix1 constraint input commands read with succes
Fix1 constraint input commands read with succes
bearing2 constraint input commands read with succes
bearing2 constraint input commands read with succes
bearing2 constraint input commands read with succes
constraint input commands read with succes
Topologi commands read with succes
Tower shadow (potential2 flow) commands read with succes
Wind commands read with succes
aerodrag element commands read with succes
aerodrag element commands read with succes
Aerodrag commands read with succes
Aerodynamic commands read with succes
output commands read with succes
Output commands read
Dll type2 input commands read with succes
output commands read with succes
Output commands read
Actions commands read
Dll type2 input commands read with succes
output commands read with succes
Output commands read
Actions commands read
Dll type2 input commands read with succes
output commands read with succes
Output commands read
Actions commands read
Dll type2 input commands read with succes
output commands read with succes
Output commands read
Dll type2 input commands read with succes
DLL commands read with succes
output commands read with succes
Output commands read
output_at read with succes
Initialization of structure
Initializing of aero rotor...
Initialization of rotor aerodynamics
Succes opening ./data/dtu_10mw_rwt_ae.dat
Succes opening ./data/dtu_10mw_rwt_pc.dat
Initialization of rotor induction
Initialization of wind
Initialization of external type2 DLL
External DLL ./control/dtu_we_controller.dll is attempted to open
Using ./control/dtu_we_controller.dll, version: unknown
Succes opening external DLL ./control/dtu_we_controller.dll
DLL subroutine init init_regulation is called
In initialization call of ./control/dtu_we_controller.dll Output is
0.000000000000000E+000
*** INFO *** The DLL subroutine message could not be loaded - bypassed!
Initialization of external type2 DLL
External DLL ./control/generator_servo.dll is attempted to open
Using ./control/generator_servo.dll, version: unknown
Succes opening external DLL ./control/generator_servo.dll
DLL subroutine init init_generator_servo is called
In initialization call of ./control/generator_servo.dll Output is
0.000000000000000E+000
*** INFO *** The DLL subroutine message could not be loaded - bypassed!
Initialization of external type2 DLL
External DLL ./control/mech_brake.dll is attempted to open
Using ./control/mech_brake.dll, version: unknown
Succes opening external DLL ./control/mech_brake.dll
DLL subroutine init init_mech_brake is called
In initialization call of ./control/mech_brake.dll Output is
0.000000000000000E+000
*** INFO *** The DLL subroutine message could not be loaded - bypassed!
Initialization of external type2 DLL
External DLL ./control/servo_with_limits.dll is attempted to open
Using ./control/servo_with_limits.dll, version: unknown
Succes opening external DLL ./control/servo_with_limits.dll
DLL subroutine init init_servo_with_limits is called
In initialization call of ./control/servo_with_limits.dll Output is
0.000000000000000E+000
*** INFO *** The DLL subroutine message could not be loaded - bypassed!
Initialization of external type2 DLL
External DLL ./control/towclearsens.dll is attempted to open
Using ./control/towclearsens.dll, version: unknown
Succes opening external DLL ./control/towclearsens.dll
DLL subroutine init initialize is called
In initialization call of ./control/towclearsens.dll Output is
2.66000000000000
*** INFO *** The DLL subroutine message could not be loaded - bypassed!
Creating link between structure and aerodynamics
Creating link between structure and aerodrag
Initialization of Aerodrag
Starting simulation
Dynamic stall method: 2 used for entire rotor
Global time = 2.000000000000000E-002 Iter = 2
Global time = 4.000000000000000E-002 Iter = 2
Global time = 6.000000000000000E-002 Iter = 2
Global time = 8.000000000000000E-002 Iter = 2
Global time = 0.100000000000000 Iter = 2
Global time = 0.120000000000000 Iter = 2
Global time = 0.140000000000000 Iter = 2
Global time = 0.160000000000000 Iter = 2
Global time = 0.180000000000000 Iter = 2
Global time = 0.200000000000000 Iter = 2
Global time = 0.220000000000000 Iter = 2
Global time = 0.240000000000000 Iter = 2
Global time = 0.260000000000000 Iter = 2
Global time = 0.280000000000000 Iter = 3
Global time = 0.300000000000000 Iter = 3
Global time = 0.320000000000000 Iter = 3
Global time = 0.340000000000000 Iter = 3
Global time = 0.360000000000000 Iter = 3
Global time = 0.380000000000000 Iter = 3
Global time = 0.400000000000000 Iter = 3
Global time = 0.420000000000000 Iter = 3
Global time = 0.440000000000000 Iter = 3
Global time = 0.460000000000000 Iter = 3
Global time = 0.480000000000000 Iter = 3
Global time = 0.500000000000000 Iter = 3
Global time = 0.520000000000000 Iter = 3
Global time = 0.540000000000000 Iter = 2
Global time = 0.560000000000000 Iter = 3
Global time = 0.580000000000000 Iter = 3
Global time = 0.600000000000000 Iter = 3
Global time = 0.620000000000000 Iter = 3
Global time = 0.640000000000000 Iter = 3
Global time = 0.660000000000000 Iter = 3
Global time = 0.680000000000000 Iter = 3
Global time = 0.700000000000000 Iter = 3
Global time = 0.720000000000000 Iter = 3
Global time = 0.740000000000000 Iter = 2
Global time = 0.760000000000000 Iter = 3
Global time = 0.780000000000000 Iter = 3
Global time = 0.800000000000000 Iter = 2
Global time = 0.820000000000000 Iter = 2
Global time = 0.840000000000000 Iter = 3
Global time = 0.860000000000000 Iter = 2
Global time = 0.880000000000000 Iter = 2
Global time = 0.900000000000000 Iter = 3
Global time = 0.920000000000000 Iter = 3
Global time = 0.940000000000000 Iter = 2
Global time = 0.960000000000000 Iter = 2
Global time = 0.980000000000000 Iter = 2
Global time = 1.00000000000000 Iter = 3
Closing of external type2 DLL
Closing of external type2 DLL
Closing of external type2 DLL
Closing of external type2 DLL
Closing of external type2 DLL
Elapsed time : 0.9218750
%% Cell type:code id: tags:
``` python
```
This diff is collapsed.
# Tutorial 1: Creating master Excel file
The Wind Energy Toolbox has a workflow for automatically running design load
bases (DLBs) on Gorm.
This workflow has the following steps:
1. Create a master Excel sheet defining each case in the DLB
2. [Create subordinate Excel sheets from each tab in the master Excel sheet](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/tutorials/2-creating-subordinate-excels.md)
3. [Create htc files and PBS job scripts for each requisite simulation using
the subordinate Excel files and a master htc file.](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/tutorials/3-creating-htc-pbs-files.md)
4. Submit all PBS job scripts to the cluster
5. Post-process results
6. Visualize results
This tutorial presents how to accomplish Step 1.
Note that it is possible to customize your simulations by skipping/modifying
steps.
Such a procedure will be discussed in a later tutorial.
If there are any problems with this tutorial, please [submit an issue](
https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/issues).
## 1. Background: Master Excel File
The master Excel file is an Excel file that is used to create subordinate
Excel files for generation of htc files and PBS job scripts.
### Master file structure
The master Excel file has a main tab, called "Main", that defines default
values and necessary functions that are called in the other tabs.
Each other tab defines a new case, and one subordinate Excel file will be
generated for each case.
There are three variable types in the master Excel file:
- Constants: values that do not change within a case
- Variables: values that do change within a case, but are numbers that do not
depend on any other values (e.g., wind speed in DLC 1.2)
- Functions: values that depend on other values
### Tag names
The values that are defined in the master Excel file (and eventually the
subordinate Excel files) are used to replace "tags" in the master htc file.
These tags are of the form ```[$TAG_NAME]```.
Theoretically, a user can define any new tags they desire, there are no
require naming conventions.
However, there are some tags that are currently hard-coded into the Toolbox
that can result in errors if the tag names are changed.
Thus, **we do not recommend you change the tag names from those in the
tutorial**.
If you need new values that do not exist in the tutorial's master htc file
and produced master file, then it should be fine to add them.
There are a few tags that deserve special mention:
- ```[Case folder]```: the htc files for each case will be saved in this case
folder. We do not recommend changing the tag name or naming convention here
if you are doing a standard DLB.
- ```[Case id.]```: this defines the naming convention for each htc file. We
do not recommend changing the tag name or naming convention here if you are
doing a standard DLB.
- ```[seed]```: this variable indicates the desired number of seeds for each
set of variables. Thus, for example, in DLC 1.2, 1.3, the ```[seed]``` value
should be set to at least 6.
Lastly, it is extremely important that your tag names in your master Excel
file match the tag names in your master htc file.
Thus, **be sure to verify that your tag names in your master Excel and master
htc files are consistent**.
## 2. Tutorial
The procedure for creating the master Excel sheet is simple: each desired DLB
is defined in a tab-delimited text file, and these are loaded into a single
Excel file.
It is assumed that the user has a collection of text files in a folder for
all of the DLBs to be simulated.
This tutorial uses the text files located in
```wetb/docs/tutorials/data/DLCs_onshore```, which contain a series of text
files for a full DLB of an onshore turbine.
These text files correspond to the onshore DTU 10 MW master htc file that is
located in the same directoy.
Generate the master Excel file in a few easy steps:
1. Open a command window.
2. If you are running the tutorial locally (i.e., not on Gorm), navigate to
the Wind Energy Toolbox tutorials directory.
3. From a terminal/command window, run the code to generate the Excel file
from a folder of text files:
* Windows (from the wetb tutorials folder):
```python ..\..\wetb\prepost\write_master.py --folder data\DLCs_onshore --filename DLCs_onshore.xlsx```
* Mac/Linux (from the wetb tutorials folder):
```python ../../wetb/prepost/write_master.py --folder data/DLCs_onshore --filename DLCs_onshore.xlsx```
* Gorm (from any folder that contains a subfolder with your text files. Note
you must activate the wetb environment (see Step 5 [here](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/getting-started-with-dlbs.md)
) before this command will work. This command also assumes the folder with your
text files is called "DLCs_onshore" and is located in the working directory.):
```python /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/write_master.py --folder ./DLCs_onshore --filename ./DLCs_onshore.xlsx```
The master Excel file "DLCs_onshore.xlsx" should now be in the your current
directory.
Note that we have used the parser options ```--folder``` and ```--filename```
to specify the folder with the text files and the name of the resulting Excel
file.
Other parser options are also available.
(See doc string in ```write_master.py``` function.)
## 3. Generation options
See doc string in ```write_master.py``` function.
## 4. Issues
If there are any problems with this tutorial, please [submit an issue](
https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/issues).
We will try to fix it as soon as possible.
# Tutorial 2: Creating subordinate Excel files
The Wind Energy Toolbox has a workflow for automatically running design load
bases (DLBs) on Gorm.
This workflow has the following steps:
1. [Create a master Excel sheet defining each case in the DLB](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/tutorials/1-creating-master-excel.md)
2. Create subordinate Excel sheets from each tab in the master Excel sheet
3. [Create htc files and PBS job scripts for each requisite simulation using
the subordinate Excel files and a master htc file.](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/tutorials/3-creating-htc-pbs-files.md)
4. Submit all PBS job scripts to the cluster
5. Post-process results
6. Visualize results
This tutorial presents how to accomplish Step 2.
Note that it is possible to customize your simulations by skipping/modifying
steps.
Such a procedure will be discussed in a later tutorial.
If there are any problems with this tutorial, please [submit an issue](
https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/issues).
## 1. Background: Subordinate Excel Files
The subordinate Excel files are a series of basic Excel files that are
generated from the master Excel file. (See our tutorial on generating the
master Excel file [here]( https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/tut orials/1-creating-master-excel.md).)
There is a different subordinate Excel file for every tab in the master Excel
file, except for the "Main" tab, one for each case to simulate (e.g., design
load case 1.2 from IEC-61400-1).
Each subordinate Excel file has a single tab that lists the different tag
values for the htc master file in the column, and each row corresponds to a
different htc file to be generated.
The generation of the htc files from the subordinate Excel files is discused
in the next tutorial.
## 2. Tutorial
The generation of the subordinate Excel files is done using the
[GenerateDLS.py](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/wetb/prepost/GenerateDLCs.py)
function in the Wind Energy Toolbox.
On Gorm, the command can be executed from the htc directory with the master
Excel file as follows:
```
export PATH=/home/python/miniconda3/bin:$PATH
source activate py36-wetb
python /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/GenerateDLCs.py [--folder=$FOLDER_NAME] [--master=$MASTER_NAME]
source deactivate
```
The ```export PATH``` command adds the miniconda bin directory to the path,
which is necessary for the toolbox.
The ```source activate py36-wetb``` and ```source deactivate``` are
Gorm-specific commands to activate the Wind Energy Toolbox Python environment.
The ```--folder``` and ```--master``` flags are optional flags to specify,
respectively, the name of the folder to which the subordinate Excel files
should be written to and the name of the master Excel file.
The default values for these two options are './' (i.e., the current
directory) and 'DLCs.xlsx', respectively.
After running the commands in the above box on Gorm, you should see a folder in
your htc directory with all of your subordinate Excel files.
## 3. Issues
If there are any problems with this tutorial, please [submit an issue](
https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/issues).
We will try to fix it as soon as possible.
# Tutorial 3: Creating htc and PBS files
The Wind Energy Toolbox has a workflow for automatically running design load
bases (DLBs) on Gorm.
This workflow has the following steps:
1. [Create a master Excel sheet defining each case in the DLB](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/tutorials/1-creating-master-excel.md)
2. [Create subordinate Excel sheets from each tab in the master Excel sheet](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/docs/tutorials/2-creating-subordinate-excels.md)
3. Create htc files and PBS job scripts for each requisite simulation using
the subordinate Excel files and a master htc file.
4. Submit all PBS job scripts to the cluster
5. Post-process results
6. Visualize results
This tutorial presents how to accomplish Step 3.
Note that it is possible to customize your simulations by skipping/modifying
steps.
Such a procedure will be discussed in a later tutorial.
If there are any problems with this tutorial, please [submit an issue](
https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/issues).
## 1. Background: htc and PBS file creation
The main function used in this tutorial is [dlctemplate.py](https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/blob/master/wetb/prepost/dlctemplate.py),
which creates all htc and PBS job scripts for the cases specified in the
subordinate Excel file folder.
The htc files are the main input files for HAWC2 simulations.
They are created by copying the master htc file in the ```_master/``` folder in
your htc directory and replacing all of the tags with the values specified in
the subordinate Excel files.
All of htc files for a single case are saved in a case-specific folder in your
htc folder.
Thus, if you were running a standard DLB calculation for IEC 61400-1, your
folder structure after generating your htc files might look like this:
```
|-- $TURB_NAME/
| |-- $SET_ID/
| | |-- DLCs.xlsx
| | |-- _master/
| | | |-- $MASTER_NAME.htc
| | |-- DLCs/
| | |-- htc/
| | | |-- dlc12_iec61400-1ed3/
| | | | |-- dlc12_wsp04_wdir000_s2001.htc
| | | | |-- dlc12_wsp04_wdir000_s2002.htc
| | | | |-- ...
| | | |-- dlc13_iec61400-1ed3/
| | | |-- ...
```
The PBS job scripts are a series of text files that are used to tell the job
scheduler on the high-performance computing (HPC) cluster how to run each job.
These files end with ".p", and are saved to a folder ```pbs_in/``` that is
created in the main set ID folder on Gorm.
## 2. Tutorial
There are two ways to call ```dlctemplate.py```.
The first is to call the function directly.
The second is to wrap it in a job scheduler to submit the job to the HPC cluster.
The first option is fine if you have only a few htc files or if the job
scheduler is not working for some reason.
The second option is generally preferred.
### 2.1 Directly generate htc files
The htc and PBS files can be directly generated by running the following
commands from the set ID directory:
```
export PATH=/home/python/miniconda3/bin:$PATH
source activate py36-wetb
python /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/dlctemplate.py --prep
source deactivate
```
The ```export PATH``` command adds the miniconda bin directory to the path,
which is necessary for the toolbox.
The ```source activate py36-wetb``` and ```source deactivate``` are
Gorm-specific commands to activate the Wind Energy Toolbox Python environment.
The ```--prep``` option tells the script to run in preparation mode, in which
case it creates the htc and pbs files.
After running the commands in the above box on Gorm, you should have all of your
PBS input files in ```pbs_in/``` and all of your htc files in ```htc```.
### 2.2 Generate files using job scheduler
From the set ID folder, run the following code:
```
qsub-wrap.py -f /home/MET/repositories/toolbox/WindEnergyToolbox/wetb/prepost/dlctemplate.py --prep
```
## 3. Issues
If there are any problems with this tutorial, please [submit an issue](
https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/issues).
We will try to fix it as soon as possible.
C F V V V F
[Case folder] [Case id.] [wdir] [seed] [wsp] [TI]
DLC12_IEC61400-1Ed3 """DLC12_wsp[wsp]_wdir[wdir]_s[seed]""" 0 6 4 "([ref_ti]*(0,75*[wsp]+5,6))/[wsp]"
350 6
10 8
10
12
14
16
18
20
22
24
26