diff --git a/.github/workflows/automated-dev-tests.yml b/.github/workflows/automated-dev-tests.yml
index 7da144a293..3567571a2d 100644
--- a/.github/workflows/automated-dev-tests.yml
+++ b/.github/workflows/automated-dev-tests.yml
@@ -41,12 +41,14 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
+ sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
- name: Setup workspace
run: cmake -E make_directory ${{runner.workspace}}/openfast/build
- name: Configure build
@@ -57,6 +59,8 @@ jobs:
-DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \
-DCMAKE_CXX_COMPILER:STRING=${{env.CXX_COMPILER}} \
-DCMAKE_C_COMPILER:STRING=${{env.C_COMPILER}} \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBLA_VENDOR:STRING=OpenBLAS \
-DCMAKE_BUILD_TYPE:STRING=DEBUG \
-DBUILD_SHARED_LIBS:BOOL=OFF \
-DGENERATE_TYPES=ON \
@@ -85,6 +89,10 @@ jobs:
uses: actions/checkout@main
with:
submodules: recursive
+ - name: Install dependencies
+ run: |
+ sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev
- name: Setup workspace
run: cmake -E make_directory ${{runner.workspace}}/openfast/build
- name: Configure build
@@ -95,6 +103,8 @@ jobs:
-DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \
-DCMAKE_CXX_COMPILER:STRING=${{env.CXX_COMPILER}} \
-DCMAKE_C_COMPILER:STRING=${{env.C_COMPILER}} \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBLA_VENDOR:STRING=OpenBLAS \
-DCMAKE_BUILD_TYPE:STRING=DEBUG \
-DBUILD_SHARED_LIBS:BOOL=OFF \
-DVARIABLE_TRACKING=OFF \
@@ -117,12 +127,14 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
+ sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
- name: Setup workspace
run: cmake -E make_directory ${{runner.workspace}}/openfast/build
- name: Configure build
@@ -133,6 +145,8 @@ jobs:
-DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \
-DCMAKE_CXX_COMPILER:STRING=${{env.CXX_COMPILER}} \
-DCMAKE_C_COMPILER:STRING=${{env.C_COMPILER}} \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBLA_VENDOR:STRING=OpenBLAS \
-DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \
-DVARIABLE_TRACKING=OFF \
-DBUILD_TESTING:BOOL=ON \
@@ -159,13 +173,14 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev # gcovr
- name: Setup workspace
run: cmake -E make_directory ${{runner.workspace}}/openfast/build
@@ -177,6 +192,8 @@ jobs:
-DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \
-DCMAKE_CXX_COMPILER:STRING=${{env.CXX_COMPILER}} \
-DCMAKE_C_COMPILER:STRING=${{env.C_COMPILER}} \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBLA_VENDOR:STRING=OpenBLAS \
-DCMAKE_BUILD_TYPE:STRING=RELWITHDEBINFO \
-DOPENMP:BOOL=ON \
-DDOUBLE_PRECISION=ON \
@@ -209,14 +226,21 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
+ - name: Configure build
+ working-directory: ${{runner.workspace}}/openfast/build
+ run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ ${GITHUB_WORKSPACE}
- name: Build OpenFAST C-Interfaces
working-directory: ${{runner.workspace}}/openfast/build
run: |
@@ -240,14 +264,21 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
+ - name: Configure build
+ working-directory: ${{runner.workspace}}/openfast/build
+ run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ ${GITHUB_WORKSPACE}
- name: Build OpenFAST glue-code
working-directory: ${{runner.workspace}}/openfast/build
run: |
@@ -271,14 +302,21 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
+ - name: Configure build
+ working-directory: ${{runner.workspace}}/openfast/build
+ run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ ${GITHUB_WORKSPACE}
- name: Build FAST.Farm
working-directory: ${{runner.workspace}}/openfast/build
run: |
@@ -304,12 +342,14 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
+ sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev
- name: Setup workspace
run: cmake -E make_directory ${{runner.workspace}}/openfast/build
- name: Configure build
@@ -320,6 +360,7 @@ jobs:
-DCMAKE_Fortran_COMPILER:STRING=${{env.FORTRAN_COMPILER}} \
-DCMAKE_CXX_COMPILER:STRING=${{env.CXX_COMPILER}} \
-DCMAKE_C_COMPILER:STRING=${{env.C_COMPILER}} \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
-DCMAKE_BUILD_TYPE:STRING=DEBUG \
-DBUILD_SHARED_LIBS:BOOL=OFF \
-DGENERATE_TYPES=ON \
@@ -363,14 +404,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
+ - name: Configure Tests
+ working-directory: ${{runner.workspace}}/openfast/build
+ run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
- name: Run AeroDyn tests
uses: ./.github/actions/tests-module-aerodyn
with:
@@ -410,18 +460,20 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
-DBUILD_TESTING:BOOL=ON \
-DCTEST_PLOT_ERRORS:BOOL=ON \
${GITHUB_WORKSPACE}
@@ -467,14 +519,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3" vtk
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
+ - name: Configure Tests
+ working-directory: ${{runner.workspace}}/openfast/build
+ run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
- name: Run Interface / API tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
@@ -506,22 +567,28 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run 5MW tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
- ctest -VV -j8 \
+ ctest -VV -j4 \
-L openfast \
-LE "cpp|linear|python|fastlib" \
-E "5MW_OC4Semi_WSt_WavesWN|5MW_OC3Mnpl_DLL_WTurb_WavesIrr|5MW_OC4Jckt_DLL_WTurb_WavesIrr_MGrowth|5MW_OC3Trpd_DLL_WSt_WavesReg|5MW_Land_BD_DLL_WTurb"
@@ -553,17 +620,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run 5MW tests
working-directory: ${{runner.workspace}}/openfast/build
@@ -597,17 +670,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run 5MW tests
working-directory: ${{runner.workspace}}/openfast/build
@@ -641,17 +720,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run 5MW tests
working-directory: ${{runner.workspace}}/openfast/build
@@ -685,17 +770,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run 5MW tests
working-directory: ${{runner.workspace}}/openfast/build
@@ -729,17 +820,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run 5MW tests
working-directory: ${{runner.workspace}}/openfast/build
@@ -773,22 +870,28 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run OpenFAST linearization tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
- ctest -VV -j8 -L linear
+ ctest -VV -j4 -L linear
- name: Failing test artifacts
uses: actions/upload-artifact@v3
if: failure()
@@ -817,17 +920,23 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v3
with:
- python-version: '3.9'
+ python-version: '3.11'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install numpy "Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3"
sudo apt-get update -y
+ sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev
sudo apt-get install -y libhdf5-dev libopenmpi-dev libyaml-cpp-dev
- name: Configure Tests
working-directory: ${{runner.workspace}}/openfast/build
run: |
+ cmake \
+ -DPython_ROOT_DIR:STRING=${{env.pythonLocation}} \
+ -DBUILD_TESTING:BOOL=ON \
+ -DCTEST_PLOT_ERRORS:BOOL=ON \
+ ${GITHUB_WORKSPACE}
cmake --build . --target regression_test_controllers
- name: Run FAST.Farm tests
working-directory: ${{runner.workspace}}/openfast/build
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 5b54f8b4a3..eed597b9ca 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -5,20 +5,20 @@
# Required
version: 2
+# select the docker image to use: stable | latest
+build:
+ os: "ubuntu-22.04"
+ tools:
+ python: "3.11"
+
formats:
- htmlzip
# - pdf
# - epub
python:
- version: 3.7
install:
- requirements: docs/requirements.txt
- system_packages: true
-
-# select the docker image to use: stable | latest
-build:
- image: stable
sphinx:
builder: html
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2a8792b190..5c9dda9259 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -108,10 +108,18 @@ include(${CMAKE_SOURCE_DIR}/cmake/set_rpath.cmake)
if (OPENMP OR BUILD_FASTFARM OR BUILD_OPENFAST_CPP_API)
FIND_PACKAGE(OpenMP REQUIRED)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
- set(CMAKE_FORTRAN_FLAGS "${CMAKE_FORTRAN_FLAGS} ${OpenMP_FORTRAN_FLAGS}")
- set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
+ if (OpenMP_Fortran_FOUND)
+ set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}")
+ link_libraries("${OpenMP_Fortran_LIBRARIES}")
+ endif()
+ if (OpenMP_C_FOUND)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
+ link_libraries("${OpenMP_C_LIBRARIES}")
+ endif()
+ if (OpenMP_CXX_FOUND)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
+ link_libraries("${OpenMP_CXX_LIBRARIES}")
+ endif()
endif()
#-------------------------------------------------------------------------------
@@ -130,11 +138,13 @@ if (USE_LOCAL_STATIC_LAPACK)
include(ExternalProject)
ExternalProject_Add(lapack
URL http://www.netlib.org/lapack/lapack.tgz
- CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_SOURCE_DIR}/install
+ CMAKE_ARGS
+ -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_SOURCE_DIR}/install
+ -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
PREFIX ${CMAKE_BINARY_DIR}/dependencies
BUILD_BYPRODUCTS ${BLAS_LIB_PATH} ${LAPACK_LIB_PATH}
)
- set(LAPACK_LIBRARIES ${BLAS_LIB_PATH} ${LAPACK_LIB_PATH} CACHE STRING "LAPACK library" FORCE)
+ set(LAPACK_LIBRARIES ${LAPACK_LIB_PATH} ${BLAS_LIB_PATH} CACHE STRING "LAPACK library" FORCE)
install(FILES ${LAPACK_LIBRARIES} DESTINATION ${CMAKE_SOURCE_DIR}/install/lib)
message(STATUS "Using LAPACK libraries: ${LAPACK_LIBRARIES}")
else()
diff --git a/docs/OtherSupporting/OutListParameters.xlsx b/docs/OtherSupporting/OutListParameters.xlsx
index 03146fa76a..ff41b567f5 100644
Binary files a/docs/OtherSupporting/OutListParameters.xlsx and b/docs/OtherSupporting/OutListParameters.xlsx differ
diff --git a/docs/changelogs/v3.5.0.md b/docs/changelogs/v3.5.0.md
index 03185c77f7..27d5ac8792 100644
--- a/docs/changelogs/v3.5.0.md
+++ b/docs/changelogs/v3.5.0.md
@@ -98,6 +98,12 @@ See GitHub Actions
#1493 Allow Non-Uniform Force Point Distribution on Blades @mchurchf
+### SubDyn
+
+#1413 Implementing directional cosine matrices and section properties for rectangular members
+#1526 Remove static improvement method (SIM) from the SubDyn elastic output mesh (y3mesh)
+#1531 BugFix - diameter not set properly for rectangular beams
+
## API changes
diff --git a/docs/source/user/aerodyn/appendix.rst b/docs/source/user/aerodyn/appendix.rst
index 6fd5b7f22b..0f60e7cf7d 100644
--- a/docs/source/user/aerodyn/appendix.rst
+++ b/docs/source/user/aerodyn/appendix.rst
@@ -51,27 +51,34 @@ The blade data input file contains the nodal discretization, geometry, twist, ch
AeroDyn List of Output Channels
-------------------------------
-This is a list of output parameters for the AeroDyn module. The names are grouped by meaning, but can be ordered in the OUTPUTS section of the AeroDyn input file as you see fit. :math:`B \alpha N \beta`, refers to output node :math:`\beta` of blade :math:`\alpha`, where :math:`\alpha` is a number in the range [1,3] and :math:`\beta` is a number in the range [1,9], corresponding to entry :math:`\beta` in the :math:`\textit{BlOutNd}` list. :math:`\textit{TwN}\beta` refers to output node :math:`\beta` of the tower and is in the range [1,9], corresponding to entry :math:`\beta` in the :math:`\textit{TwOutNd}` list. A comprehensive, up-to-date list of all possible output parameters is given in the Excel file :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>`.
-The local tower coordinate system is shown in :numref:`ad_tower_geom` and the local blade coordinate system is shown in :numref:`ad_blade_local_cs` below. Figure :numref:`ad_blade_local_cs` also shows the direction of the local angles and force components.
+AeroDyn has regular outputs (see :numref:`AD-Outputs`) and nodal outputs (see :numref:`AD-Nodal-Outputs`).
-.. _ad_blade_local_cs:
+The coordinate systems used for the outputs (labeled, i, h, p, l, a) are described in :numref:`ad_coordsys`.
-.. figure:: figs/aerodyn_blade_local_cs.png
- :width: 80%
- :align: center
- :alt: aerodyn_blade_local_cs.png
- AeroDyn Local Blade Coordinate System (Looking Toward the Tip,
- from the Root) – l: Lift, d: Drag, m: Pitching, x: Normal (to Plane),
- y: Tangential (to Plane), n: Normal (to Chord),
- and t: Tangential (to Chord)
+A comprehensive, up-to-date list of all possible output parameters is given in the Excel file :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>`, in the tab `AeroDyn` and `AeroDyn_Nodes` for the regular and nodal outputs, respectively.
+The names in the Excel file are grouped by meaning, but can be ordered in the OUTPUTS section of the AeroDyn input file as you see fit.
-.. _ad-output-channel:
-.. figure:: figs/aerodyn_output_channel.pdf
- :width: 500px
- :align: center
- :alt: aerodyn_output_channel.pdf
- AeroDyn Output Channel List
+**Regular outputs**
+Some examples of regular outputs are given below (see :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>` for an exhaustive list):
+
+
+ - `RtAeroCp` : aerodynamic power coefficient.
+
+
+ - :math:`B \alpha N \beta`, refers to output node :math:`\beta` of blade :math:`\alpha`, where :math:`\alpha` is a number in the range [1,3] and :math:`\beta` is a number in the range [1,9], corresponding to entry :math:`\beta` in the :math:`\textit{BlOutNd}` list.
+
+ - :math:`\textit{TwN}\beta` refers to output node :math:`\beta` of the tower and is in the range [1,9], corresponding to entry :math:`\beta` in the :math:`\textit{TwOutNd}` list.
+
+
+**Nodal outputs**
+
+An example of nodal outputs is described below (see :download:`OutListParameters.xlsx <../../../OtherSupporting/OutListParameters.xlsx>` for an exhaustive list).
+
+The x-component of the undisturbed flow velocity (`VUnd`) at all blade nodes in the inertial frame (:math:`i`) is requested by placing :math:`VUndxi` in the AeroDyn nodal output list.
+This will result in output channels of the form `AB`:math:`\alpha N\beta` `Vundxi`, for node :math:`\beta` of blade :math:`\alpha`, where :math:`\alpha` is a number in the range [1,3] and :math:`\beta` is a number in the range [1,999] corresponding to the index of the AeroDyn blade node.
+
+
diff --git a/docs/source/user/aerodyn/conf.py b/docs/source/user/aerodyn/conf.py
index 330c0dfcef..f6bd61d28b 100644
--- a/docs/source/user/aerodyn/conf.py
+++ b/docs/source/user/aerodyn/conf.py
@@ -21,10 +21,36 @@
import subprocess
import re
-
from sphinx.highlighting import PygmentsBridge
from pygments.formatters.latex import LatexFormatter
+#sys.path.append(os.path.abspath('_extensions/'))
+
+readTheDocs = os.environ.get('READTHEDOCS', None) == 'True'
+builddir = sys.argv[-1]
+sourcedir = sys.argv[-2]
+
+# Use this to turn Doxygen on or off
+useDoxygen = False
+
+# This function was adapted from https://gitlab.kitware.com/cmb/smtk
+# Only run when on readthedocs
+def runDoxygen(sourcfile, doxyfileIn, doxyfileOut):
+ dx = open(os.path.join(sourcedir, doxyfileIn), 'r')
+ cfg = dx.read()
+ srcdir = os.path.abspath(os.path.join(os.getcwd(), '..'))
+ bindir = srcdir
+ c2 = re.sub('@CMAKE_SOURCE_DIR@', srcdir, re.sub('@CMAKE_BINARY_DIR@', bindir, cfg))
+ doxname = os.path.join(sourcedir, doxyfileOut)
+ dox = open(doxname, 'w')
+ print(c2, file=dox)
+ dox.close()
+ print("Running Doxygen on {}".format(doxyfileOut))
+ doxproc = subprocess.call(('doxygen', doxname))
+
+if readTheDocs and useDoxygen:
+ runDoxygen(sourcedir, 'Doxyfile.in', 'Doxyfile')
+
class CustomLatexFormatter(LatexFormatter):
def __init__(self, **options):
super(CustomLatexFormatter, self).__init__(**options)
@@ -32,12 +58,6 @@ def __init__(self, **options):
PygmentsBridge.latex_formatter = CustomLatexFormatter
-#sys.path.append(os.path.abspath('_extensions/'))
-
-readTheDocs = os.environ.get('READTHEDOCS', None) == 'True'
-sourcedir = sys.argv[-2]
-builddir = sys.argv[-1]
-
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
@@ -56,13 +76,32 @@ def __init__(self, **options):
'sphinxcontrib.bibtex',
]
-autodoc_default_flags = ['members','show-inheritance','undoc-members']
+autodoc_default_flags = [
+ 'members',
+ 'show-inheritance',
+ 'undoc-members'
+]
autoclass_content = 'both'
mathjax_path = 'https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML'
# FIXME: Naively assuming build directory one level up locally, and two up on readthedocs
+if useDoxygen:
+ if readTheDocs:
+ doxylink = {
+ 'openfast': (
+ os.path.join(builddir, '..', '..', 'openfast.tag'),
+ os.path.join('html')
+ )
+ }
+ else:
+ doxylink = {
+ 'openfast': (
+ os.path.join(builddir, '..', 'openfast.tag'),
+ os.path.join('html')
+ )
+ }
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -79,7 +118,7 @@ def __init__(self, **options):
# General information about the project.
project = u'AeroDyn'
filename = project.replace(' ','_')
-copyright = u'2017, National Renewable Energy Laboratory'
+copyright = u'2023, National Renewable Energy Laboratory'
author = u'OpenFAST Team'
# The version info for the project you're documenting, acts as replacement for
@@ -96,7 +135,7 @@ def __init__(self, **options):
#
# 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
+# language = None # Default is English and None is not a valid option
#If true, figures, tables and code-blocks are automatically numbered if they
#have a caption. At same time, the numref role is enabled. For now, it works
@@ -108,6 +147,13 @@ def __init__(self, **options):
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+# FIXME: Naively assuming build directory one level up locally, and two up on readthedocs
+if useDoxygen:
+ if readTheDocs:
+ html_extra_path = [os.path.join(builddir, '..', '..', 'doxygen')]
+ else:
+ html_extra_path = [os.path.join(builddir, '..', 'doxygen')]
+
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
@@ -147,12 +193,15 @@ def __init__(self, **options):
# 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',
@@ -162,8 +211,13 @@ def __init__(self, **options):
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, '{}.tex'.format(filename), u'{} Documentation'.format(project),
- u'National Renewable Energy Laboratory', 'manual'),
+ (
+ master_doc,
+ '{}.tex'.format(filename),
+ u'{} Documentation'.format(project),
+ u'National Renewable Energy Laboratory',
+ 'manual'
+ ),
]
@@ -172,8 +226,13 @@ def __init__(self, **options):
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
- (master_doc, project, u'{} Documentation'.format(project),
- [author], 1)
+ (
+ master_doc,
+ project,
+ u'{} Documentation'.format(project),
+ [author],
+ 1
+ )
]
@@ -183,19 +242,34 @@ def __init__(self, **options):
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, filename, u'{} Documentation'.format(project),
- author, project, 'One line description of project.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ filename,
+ u'{} Documentation'.format(project),
+ author,
+ project,
+ 'One line description of project.',
+ 'Miscellaneous'
+ ),
]
def setup(app):
- app.add_object_type("confval", "confval",
- objname="input file parameter",
- indextemplate="pair: %s; input file parameter")
- app.add_object_type("cmakeval", "cmakeval",
- objname="CMake configuration value",
- indextemplate="pair: %s; CMake configuration")
-
+ try:
+ app.add_css_file('css/math_eq.css')
+ except:
+ pass
+ app.add_object_type(
+ "confval",
+ "confval",
+ objname="input file parameter",
+ indextemplate="pair: %s; input file parameter"
+ )
+ app.add_object_type(
+ "cmakeval",
+ "cmakeval",
+ objname="CMake configuration value",
+ indextemplate="pair: %s; CMake configuration"
+ )
# --- Prolog that will be included at the top of every rst file
# Here: defining the role :red: for html and latex
rst_prolog = r"""
@@ -216,3 +290,4 @@ def setup(app):
.. role:: red
"""
+
diff --git a/docs/source/user/aerodyn/coordsys.rst b/docs/source/user/aerodyn/coordsys.rst
new file mode 100644
index 0000000000..060e480c61
--- /dev/null
+++ b/docs/source/user/aerodyn/coordsys.rst
@@ -0,0 +1,304 @@
+
+.. _ad_coordsys:
+
+Coordinate systems
+==================
+
+AeroDyn uses different coordinate system for its internal computations and its outputs.
+The output channels are typically suffixed with a letter corresponding to the coordinate system being used:
+
+* (i): inertial system
+* (h): hub system
+* (p): polar system
+* (l): local-polar system
+* None or (w): the legacy output system.
+* (n-t): the legacy airfoil system.
+
+The different systems are described below.
+
+
+
+
+Inertial system (i)
+-------------------
+
+The inertial system :math:`(i)` is the global system used by OpenFAST (see ElastoDyn documentation).
+
+
+
+Hub system (h)
+--------------
+
+The hub system :math:`(h)` rotates along the :math:`x_h` axis based on the shaft azimuthal position :math:`\psi` (see ElastoDyn documentation).
+
+
+Polar system (p)
+----------------
+
+The polar system :math:`(p_k)` is constructed from the hub coordinate system :math:`(h)`
+by rotating the :math:`x_h` axis by the azimuthal offset of each blade :math:`\psi_{0,k}` (the blades are distributed evenly across the azimuth).
+For conciseness we refer to this system as the :math:`(p)` system.
+If the number of blade is written :math:`n_B`, the azimuthal offset for blade :math:`k` is:
+
+.. math::
+
+ \begin{aligned}
+ \psi_{0,k} = 2 \pi \frac{k-1}{n_B}
+ \end{aligned}
+
+For blade 1, :math:`\psi_{0,1}=0`, therefore :math:`y_{p,1}=y_h` and :math:`z_{p,1}=z_h`.
+
+The :math:`x_{p,k}` axis is along the hub x-axis.
+
+
+In the absence of coning, the :math:`z_{p,k}` axis corresponds to the :math:`z_{b,k}` axis of the blade.
+
+
+Cone system (c)
+---------------
+
+The cone system :math:`(c)` is obtained from the polar system by a rotation about the :math:`y_{p,k}` axis of each blade :math:`k`.
+See ElastoDyn/FAST8 documentation for more details.
+AeroDyn uses this system to estimate the blade pitch angle (by comparing the :math:`(c)` and :math:`(b)` systems).
+
+
+
+Blade system (b)
+----------------
+
+The blade system :math:`(b)` is otbained from the cone system by a rotation (pitching) about the :math:`z_c` axis.
+It is used to define the location of the aerodynamic center, the local twist of the blade along the span of the blade.
+See :numref:`blade_data_input_file` and :numref:`ad_blade_geom`.
+
+
+
+
+Airfoil system (a)
+------------------
+
+**Currently the user specifies the prebend orientation in the input file and it is used to orient the airfoil** (i.e. the axis :math:`z_a`). In the future, this orientation may be computed automatically from the AC-line.
+
+
+The airfoil section system :math:`(a_{_{kj}})`, or :math:`(a)` for short, is the coordinate system where Blade Element Theory is applied, and where the airfoil shape and polar data are given.
+The airfoil coordinate system, :math:`(a_{_{kj}})` is defined for each blade :math:`k` and each blade node :math:`j`.
+The :math:`y_a` axis is along the airfoil chord (tangential to chord), towards the trailing
+edge.
+The :math:`x_a` axis is normal to chord, towards the suction side (for an asymmetric airfoil).
+See :numref:`ad_cs_airfoil`.
+
+
+
+.. _ad_cs_airfoil:
+
+.. figure:: figs/FASTAirfoilSystem.svg
+ :width: 80%
+ :align: center
+
+ The airfoil (a) coordinate system.
+
+
+The :math:`(a)` system is where Blade Element Theory (BET) is applied: the angle of attack, :math:`\alpha`, the lift, :math:`L`, and drag, :math:`D`, are all defined in the :math:`x_a-y_a` plane.
+The lifting line loads are computed in this system.
+The relative wind in this system is the projection of the 3D
+relative wind into the 2D plane of the :math:`(a)`-system, noted :math:`{}^{\perp_a}\boldsymbol{V}_\text{rel}` or :math:`\boldsymbol{V}_\text{rel,a}`.
+
+In the airfoil system, we have:
+
+.. math::
+
+ \begin{aligned}
+ C_{x_a} = C_l(\alpha) \cos\alpha + C_d(\alpha)\sin\alpha % that's Cn
+ ,\quad
+ C_{y_a} = -C_l(\alpha) \sin\alpha + C_d(\alpha)\cos\alpha % that's -Ct for the t of AeroDyn
+ ,\quad
+ C_{m_a} = C_m(\alpha)
+ \end{aligned}
+
+and the loads (per unit length) are:
+
+.. math::
+
+ \begin{aligned}
+ f_{x_a} = \frac{1}{2}\rho V_{\text{rel},a}^2 c C_{x_a}
+ ,\quad
+ f_{y_a} = \frac{1}{2}\rho V_{\text{rel},a}^2 c C_{y_a}
+ ,\quad
+ m_{z_a} = \frac{1}{2}\rho V_{\text{rel},a}^2 c^2 C_{m_a}
+ \end{aligned}
+
+
+
+Legacy (n-t) system
+-------------------
+
+In legacy AeroDyn code and documentation, the :math:`(n-t)` system is sometimes used.
+The :math:`n`-axis corresponds to the :math:`x_a` axis (normal to chord).
+The :math:`t`-axis corresponds to the :math:`-y_a` axis (opposite direction).
+
+
+
+
+Local polar system (l)
+----------------------
+
+**Currently the local polar system is only used for output purposes. It will be used in the BEM implementation in future releases.**
+
+
+The local polar coordinate system :math:`(l_{_{kj}})`, or :math:`(l)` for short, is similar to the polar coordinate system, but is rotated about the :math:`x_h` axis, such that the :math:`z_{l,kj}` axis passes through the deflected position of node :math:`j` of blade :math:`k`.
+
+:math:`x_l` is along the hub :math:`x_h` axis,
+and :math:`z_l` is the radial coordinate in the plane normal to the shaft axis.
+The coordinate system is illustrated in :numref:`ad_cs_localpolar` for a case with prebend only (left) and presweep only (right).
+
+
+
+.. _ad_cs_localpolar:
+
+.. figure:: figs/FASTLocalPolarSystem.svg
+ :width: 70%
+ :align: center
+
+ The polar (p) and local polar (l) coordinate systems.
+ Left: pure prebend.
+ Right: pure sweep.
+
+
+The local polar coordinate system is defined for each blade node as follows. The position of a deflected blade node :math:`A_j` with respect to the hub :math:`H` is :
+
+ .. math::
+
+ \begin{aligned}
+ \boldsymbol{r}_{HA_j} = \boldsymbol{r}_{A_j}-\boldsymbol{r}_H
+ \end{aligned}
+
+This vector is projected onto the rotor plane as follows:
+
+ .. math::
+
+ \begin{aligned}
+ \boldsymbol{r}_{HA_j}^\perp = \mathop{\mathrm{\boldsymbol{\mathrm{P}}}}_{\boldsymbol{\hat{x}}_h}(\boldsymbol{r}_{HA_j}) = \boldsymbol{r}_{HA_j} - (\boldsymbol{\hat{x}}_h \cdot {\boldsymbol{r}_{HA_j}}) \boldsymbol{\hat{x}}_h
+ \end{aligned}
+
+
+The vectors of the local polar coordinate system are then defined as:
+
+ .. math::
+
+ \begin{aligned}
+ \boldsymbol{\hat{x}}_{l} = \boldsymbol{\hat{x}}_h
+ ,\quad
+ \boldsymbol{\hat{z}}_{l} = \frac{ \boldsymbol{r}_{HA_j}^\perp }{\lVert\boldsymbol{r}_{HA_j}\rVert}
+ ,\quad
+ \boldsymbol{\hat{y}}_{l} = \boldsymbol{\hat{z}}_h \times \boldsymbol{\hat{x}}_h
+ \end{aligned}
+
+The local polar coordinate systems of the different blade nodes differ from
+an azimuthal rotation about the :math:`x_h` axis (and a translation
+of origin about the :math:`x_h`-axis, which is mostly irrelevant).
+
+
+Legacy local output system (w)
+------------------------------
+
+**Outputs of AeroDyn labeled "x" or "y" without any other letters defining the coordinate system are currently provided in the legacy output system.** (for instance :math:`F_x`, :math:`V_x`, or :math:`V_{dis,y}`).
+
+We write :math:`(w)` the legacy output system of OpenFAST. The legacy output system has previously been documented using Figure :numref:`ad_blade_local_cs`.
+The figure also shows the direction of the local angles and force components.
+In this figure, :math:`x` should be understood as :math:`x_w` and :math:`y` as :math:`y_w`.
+The figure is mostly valid if there is no prebend, precone or presweep.
+
+
+
+.. _ad_blade_local_cs:
+
+.. figure:: figs/aerodyn_blade_local_cs.png
+ :width: 80%
+ :align: center
+ :alt: aerodyn_blade_local_cs.png
+
+ AeroDyn Legacy Local Output Coordinate System (Looking Toward the Tip,
+ from the Root) – l: Lift, d: Drag, m: Pitching, x: Normal (to Plane),
+ y: Tangential (to Plane), n: Normal (to Chord),
+ and t: Tangential (to Chord)
+
+
+
+
+
+The :math:`(w_{kj})` is defined for each blade :math:`k` and node :math:`j`, written :math:`(w)` for conciseness.
+The :math:`(w)` system is a transformation of the airfoil system such that this system has no
+rotation about the :math:`x` (sweep) or :math:`z` (pitch/twist) axis compared to the coned coordinate system.
+
+ - The :math:`y_w`-axis (in plane) of this system is orthogonal to
+ the pitch axis, neglecting presweep and in-plane deflection.
+
+ - The :math:`x_w`-axis (out of plane) is normal to the deflected
+ blade, including precurve and out-of-plane deflection.
+
+ - The :math:`z_w`-axis (radial) is tangent to the deflected blade,
+ including precurve and out-of-plane deflection.
+
+The system is constructed as follows in AeroDyn. First, the coned
+coordinate system :math:`(c)` (located at the blade root, coned, but
+without pitching) is defined using the following substeps and
+matrices:
+
+ - :math:`\boldsymbol{R}_{bi}`: from inertial to blade root (the
+ blade root is pitched by :math:`\theta_p`).
+
+ - :math:`\boldsymbol{R}_{hi}`: from inertial to hub.
+
+ - :math:`\boldsymbol{R}_{bh} = \boldsymbol{R}_{bi} \boldsymbol{R}_{hi}^t=\mathop{\mathrm{Euler}}(\theta_1, \theta_2, -\theta_p)`:
+ from hub to blade. The third Euler angle from
+ :math:`\boldsymbol{R}_{bh}` is the opposite of the pitch angle
+ :math:`\theta_p` (wind turbines use a negative convention of pitch
+ and twist about the :math:`z` axis). By setting this Euler angle
+ to zero and constructing the transformation matrix from the two
+ first angles, one obtains:
+
+ - :math:`\boldsymbol{R}_{ch}=\mathop{\mathrm{Euler}}(\theta_1, \theta_2,0)`:
+ from hub to the coned coordinate system.
+
+ - :math:`\boldsymbol{R}_{ci}=\boldsymbol{R}_{ch} \boldsymbol{R}_{hi}`:
+ from inertial to coned coordinate system.
+
+Then, the :math:`(w)` system is defined for each airfoil cross
+section:
+
+ - :math:`\boldsymbol{R}_{ai}`: from inertial to blade airfoil
+ section (include elastic motions)
+
+ - From coned system to blade airfoil section:
+
+ .. math::
+
+ \begin{aligned}
+ \boldsymbol{R}_{ac}=\boldsymbol{R}_{ai}\boldsymbol{R}_{ci}^t=\mathop{\mathrm{Euler}}({}^w\!\tau,{}^w\!\kappa,-{}^w\!\beta)
+ \label{eq:R_acBetaFull}
+ \end{aligned}
+
+ where :math:`{}^w\!\beta` contains the full twist (aerodynamic,
+ elastic and pitch), :math:`{}^w\!\tau` would be the toe angle (but
+ it is not used) :math:`{}^w\!\kappa` is the cant angle (stored as
+ ``Curve``). We use the supperscript :math:`w` because these angles
+ are defined as part of the :math:`(w)` system.
+
+ - :math:`\boldsymbol{R}_{wc}=\mathop{\mathrm{Euler}}(0,{}^w\!\kappa,0)`:
+ from coned system to :math:`w`-system. The :math:`(w)` system
+ keeps only the rotation about :math:`y_c`
+ (:math:`\approx`\ prebend), thereby neglecting the ones about
+ :math:`x` (sweep) and :math:`z` (:math:`\approx` twist+pitch).
+
+ - :math:`\boldsymbol{R}_{wi}=\boldsymbol{R}_{wc}\boldsymbol{R}_{ci}`:
+ from inertial system to :math:`w`-system
+
+
+
+
+
+
+
+Tower system
+------------
+
+The local tower coordinate system is shown in :numref:`ad_tower_geom`.
diff --git a/docs/source/user/aerodyn/figs/FASTAirfoilSystem.svg b/docs/source/user/aerodyn/figs/FASTAirfoilSystem.svg
new file mode 100644
index 0000000000..5777caa96d
--- /dev/null
+++ b/docs/source/user/aerodyn/figs/FASTAirfoilSystem.svg
@@ -0,0 +1,705 @@
+
+
+
+
diff --git a/docs/source/user/aerodyn/figs/FASTLocalPolarSystem.svg b/docs/source/user/aerodyn/figs/FASTLocalPolarSystem.svg
new file mode 100644
index 0000000000..ffbae8227a
--- /dev/null
+++ b/docs/source/user/aerodyn/figs/FASTLocalPolarSystem.svg
@@ -0,0 +1,611 @@
+
+
+
+
diff --git a/docs/source/user/aerodyn/figs/UAAirfoilSystem.png b/docs/source/user/aerodyn/figs/UAAirfoilSystem.png
deleted file mode 100644
index e123b10289..0000000000
Binary files a/docs/source/user/aerodyn/figs/UAAirfoilSystem.png and /dev/null differ
diff --git a/docs/source/user/aerodyn/figs/UAAirfoilSystem.svg b/docs/source/user/aerodyn/figs/UAAirfoilSystem.svg
index 9247086220..ec6f2d2cc2 100644
--- a/docs/source/user/aerodyn/figs/UAAirfoilSystem.svg
+++ b/docs/source/user/aerodyn/figs/UAAirfoilSystem.svg
@@ -2,19 +2,19 @@
diff --git a/docs/source/user/aerodyn/index.rst b/docs/source/user/aerodyn/index.rst
index 9fafc5a5e6..7b414b4b28 100644
--- a/docs/source/user/aerodyn/index.rst
+++ b/docs/source/user/aerodyn/index.rst
@@ -26,6 +26,7 @@ The documentation here was derived from AeroDyn Manual for AeroDyn version 15.04
:maxdepth: 2
introduction.rst
+ coordsys.rst
input.rst
output.rst
modeling.rst
diff --git a/docs/source/user/aerodyn/introduction.rst b/docs/source/user/aerodyn/introduction.rst
index 6a1a380e80..c743fc2875 100644
--- a/docs/source/user/aerodyn/introduction.rst
+++ b/docs/source/user/aerodyn/introduction.rst
@@ -199,3 +199,6 @@ file, and the results file.
using AeroDyn.
Example input files are included in :numref:`ad_input_files`. A summary of
available output channels are found :numref:`ad_output_channels`.
+
+
+
diff --git a/docs/source/user/aerodyn/theory_ua.rst b/docs/source/user/aerodyn/theory_ua.rst
index d55699d5b5..005e478fdd 100644
--- a/docs/source/user/aerodyn/theory_ua.rst
+++ b/docs/source/user/aerodyn/theory_ua.rst
@@ -45,8 +45,8 @@ the inputs present in the profile input file (including some of the ones repeate
The airfoil section coordinate system and main variables are presented in :numref:`fig:UAAirfoilSystem` and further described below:
-.. figure:: figs/UAAirfoilSystem.png
- :width: 60%
+.. figure:: figs/UAAirfoilSystem.svg
+ :width: 70%
:name: fig:UAAirfoilSystem
Definition of aifoil section coordinate system used in the unsteady aerodynamics module
diff --git a/glue-codes/fast-farm/src/FAST_Farm_Subs.f90 b/glue-codes/fast-farm/src/FAST_Farm_Subs.f90
index 12678ae2ce..1ee45ea21e 100644
--- a/glue-codes/fast-farm/src/FAST_Farm_Subs.f90
+++ b/glue-codes/fast-farm/src/FAST_Farm_Subs.f90
@@ -2710,6 +2710,17 @@ subroutine FARM_CalcOutput(t, farm, ErrStat, ErrMsg)
!$OMP END PARALLEL DO
if (ErrStat >= AbortErrLev) return
+ ! IO operation, not done using OpenMP
+ DO nt = 1,farm%p%NumTurbines
+ call WD_WritePlaneOutputs( t, farm%WD(nt)%u, farm%WD(nt)%p, farm%WD(nt)%x, farm%WD(nt)%xd, farm%WD(nt)%z, &
+ farm%WD(nt)%OtherSt, farm%WD(nt)%y, farm%WD(nt)%m, ErrStat2, ErrMsg2 )
+ if (ErrStat2 >= AbortErrLev) then
+ call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'T'//trim(num2lstr(nt))//':'//RoutineName)
+ endif
+ END DO
+ if (ErrStat >= AbortErrLev) return
+
+
call Transfer_WD_to_AWAE(farm)
if ( farm%p%UseSC ) then
diff --git a/glue-codes/simulink/CMakeLists.txt b/glue-codes/simulink/CMakeLists.txt
index f4251c35cd..1da4052938 100644
--- a/glue-codes/simulink/CMakeLists.txt
+++ b/glue-codes/simulink/CMakeLists.txt
@@ -14,6 +14,33 @@
# limitations under the License.
#
+# List of module libraries to be linked into the MEX shared library.
+# This list will be linked twice to resolve undefined symbols due to linking order.
+set(MEX_LIBS
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $
+ $ # MATLAB Specific
+ $
+ $
+ $
+ $
+ $
+ $
+ $ # MATLAB Specific
+)
+
# Build the matlab shared library (mex) using the current toolchain.
# Recommpiles FAST_* files with COMPILE_SIMULINK defined.
# Links directly to library files, bypassing dependencies so MATLAB specific
@@ -30,28 +57,8 @@ matlab_add_mex(
${PROJECT_SOURCE_DIR}/modules/openfast-library/src/FAST_Solver.f90
${PROJECT_SOURCE_DIR}/modules/openfast-library/src/FAST_Library.f90
LINK_TO
- $ # MATLAB Specific
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $
- $ # MATLAB Specific
- $
- $
- $
- $
+ ${MEX_LIBS}
+ ${MEX_LIBS} # DO NOT REMOVE (needed to ensure no unresolved symbols)
${LAPACK_LIBRARIES}
${CMAKE_DL_LIBS}
${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES}
diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90
index 2ef0eed64f..f1a94d11cb 100644
--- a/modules/aerodyn/src/AeroDyn.f90
+++ b/modules/aerodyn/src/AeroDyn.f90
@@ -604,9 +604,11 @@ subroutine Init_MiscVars(m, p, u, y, errStat, errMsg)
errStat = ErrID_None
errMsg = ""
- call AllocAry( m%DisturbedInflow, 3_IntKi, p%NumBlNds, p%numBlades, 'OtherState%DisturbedInflow', ErrStat2, ErrMsg2 ) ! must be same size as u%InflowOnBlade
+ call AllocAry( m%DisturbedInflow, 3_IntKi, p%NumBlNds, p%numBlades, 'm%DisturbedInflow', ErrStat2, ErrMsg2 ) ! must be same size as u%InflowOnBlade
call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName )
- call AllocAry( m%orientationAnnulus, 3_IntKi, 3_IntKi, p%NumBlNds, p%numBlades, 'OtherState%orientationAnnulus', ErrStat2, ErrMsg2 )
+ call AllocAry( m%orientationAnnulus, 3_IntKi, 3_IntKi, p%NumBlNds, p%numBlades, 'm%orientationAnnulus', ErrStat2, ErrMsg2 )
+ call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName )
+ call AllocAry( m%R_li, 3_IntKi, 3_IntKi, p%NumBlNds, p%numBlades, 'm%R_li', ErrStat2, ErrMsg2 )
call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName )
call allocAry( m%SigmaCavit, p%NumBlNds, p%numBlades, 'm%SigmaCavit', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
@@ -652,6 +654,8 @@ subroutine Init_MiscVars(m, p, u, y, errStat, errMsg)
call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName )
call AllocAry( m%Mz, p%NumBlNds, p%NumBlades, 'm%Mz', ErrStat2, ErrMsg2 )
call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName )
+ call AllocAry( m%Vind_i, 3, p%NumBlNds, p%NumBlades, 'm%Vind_i', ErrStat2, ErrMsg2 )
+ call SetErrStat( errStat2, errMsg2, errStat, errMsg, RoutineName )
! mesh mapping data for integrating load over entire rotor:
allocate( m%B_L_2_H_P(p%NumBlades), Stat = ErrStat2)
if (ErrStat2 /= 0) then
@@ -1836,11 +1840,12 @@ subroutine RotWriteOutputs( t, u, p, p_AD, x, xd, z, OtherState, y, m, m_AD, iRo
! NOTE: m%BEMT_u(i) indices are set differently from the way OpenFAST typically sets up the u and uTimes arrays
integer, parameter :: indx = 1 ! m%BEMT_u(1) is at t; m%BEMT_u(2) is t+dt
- integer(intKi) :: i
+ integer(intKi) :: i, k
integer(intKi) :: ErrStat2
character(ErrMsgLen) :: ErrMsg2
character(*), parameter :: RoutineName = 'RotCalcOutput'
+ real(R8Ki) :: x_hat_disk(3)
! LOGICAL :: CalcWriteOutput
!-------------------------------------------------------
! get values to output to file:
@@ -1864,6 +1869,14 @@ subroutine RotWriteOutputs( t, u, p, p_AD, x, xd, z, OtherState, y, m, m_AD, iRo
! Now we need to populate the blade node outputs here
if (p%NumBlades > 0) then
+ ! For all methods (BEM/FVW), computes R_li: from inertial system to local-polar system
+ ! NOTE: this could be placed either in AeroDyn_IO* or in SetInputs
+ ! The issue right now is the Calculate_MeshOrientation_Rel2Hub is in AeroDyn.f90
+ x_hat_disk = u%HubMotion%Orientation(1,:,1)
+ do k=1,p%NumBlades
+ ! Compute R_li for all nodes
+ call Calculate_MeshOrientation_Rel2Hub(u%BladeMotion(k), u%HubMotion, x_hat_disk, m%R_li(:,:,:,k))
+ enddo
call Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, indx, iRot, ErrStat2, ErrMsg2 ) ! Call after normal writeoutput. Will just postpend data on here.
call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
end if
@@ -2102,16 +2115,16 @@ subroutine CalcBuoyantLoads( u, p, m, y, ErrStat, ErrMsg )
BlmomentBplus(3) = BlmomentBplus(3) + BlglobCBplus(1) * BlforceBplus(2) - BlglobCBplus(2) * BlforceBplus(1)
! Sum loads at each node
- BlFBtmp(j,k,:) = BlFBtmp(j,k,:) + BlforceB
+ BlFBtmp(j,k,:) = BlFBtmp(j ,k,:) + BlforceB
BlFBtmp(j+1,k,:) = BlFBtmp(j+1,k,:) + BlforceBplus
- BlMBtmp(j,k,:) = BlMBtmp(j,k,:) + BlmomentB
+ BlMBtmp(j,k,:) = BlMBtmp(j ,k,:) + BlmomentB
BlMBtmp(j+1,k,:) = BlMBtmp(j+1,k,:) + BlmomentBplus
end do ! j = nodes
! Assign loads to point mesh
do j = 1,p%NumBlNds
- m%BladeBuoyLoadPoint(k)%Force(:,j) = BlFBtmp(j,k,:)
+ m%BladeBuoyLoadPoint(k)%Force(:,j) = BlFBtmp(j,k,:)
m%BladeBuoyLoadPoint(k)%Moment(:,j) = BlMBtmp(j,k,:)
end do ! j = nodes
@@ -2630,7 +2643,7 @@ subroutine SetInputsForBEMT(p, u, m, indx, errStat, errMsg)
!..........................
if (p%AeroProjMod==APM_BEM_NoSweepPitchTwist .or. p%AeroProjMod==APM_LiftingLine) then
- m%BEMT_u(indx)%psi = Azimuth
+ m%BEMT_u(indx)%psi_s = Azimuth
elseif (p%AeroProjMod==APM_BEM_Polar) then
do k=1,p%NumBlades
@@ -2640,7 +2653,7 @@ subroutine SetInputsForBEMT(p, u, m, indx, errStat, errMsg)
! Extract azimuth angle for blade k
! NOTE: EB, this might need improvements (express wrt hub, also deal with case hubRad=0). This is likely not psi_skew.
theta = -EulerExtract( transpose(orientationBladeAzimuth(:,:,1)) )
- m%BEMT_u(indx)%psi(k) = theta(1)
+ m%BEMT_u(indx)%psi_s(k) = theta(1)
end do !k=blades
! Find the most-downwind azimuth angle needed by the skewed wake correction model
@@ -2776,8 +2789,9 @@ subroutine SetInputsForBEMT(p, u, m, indx, errStat, errMsg)
m%BEMT_u(indx)%Vz(j,k) = dot_product( tmp, m%orientationAnnulus(3,:,j,k) ) ! radial component (tangential to the plane, not chord) of the inflow velocity of the jth node in the kth blade
! NOTE: We'll likely remove that:
- m%BEMT_u(indx)%xVelCorr(j,k) = TwoNorm(m%DisturbedInflow(:,j,k))*( sin(yaw)*sin(-m%BEMT_u(indx)%cantAngle(j,k))*sin(m%BEMT_u(indx)%psi(k)) &
- + sin(tilt)*cos(yaw)*sin(-m%BEMT_u(indx)%cantAngle(j,k))*cos(m%BEMT_u(indx)%psi(k)) ) !m%BEMT_u(indx)%Vy(j,k)*sin(-theta(2))*sin(m%BEMT_u(indx)%psi(k))
+ !m%BEMT_u(indx)%xVelCorr(j,k) = TwoNorm(m%DisturbedInflow(:,j,k))*( sin(yaw)*sin(-m%BEMT_u(indx)%cantAngle(j,k))*sin(m%BEMT_u(indx)%psi_s(k)) &
+ ! + sin(tilt)*cos(yaw)*sin(-m%BEMT_u(indx)%cantAngle(j,k))*cos(m%BEMT_u(indx)%psi_s(k)) ) !m%BEMT_u(indx)%Vy(j,k)*sin(-theta(2))*sin(m%BEMT_u(indx)%psi(k))
+ m%BEMT_u(indx)%xVelCorr(j,k) = 0.0_ReKi ! TODO
end do !j=nodes
end do !k=blades
@@ -4003,6 +4017,8 @@ SUBROUTINE Init_BEMTmodule( InputFileData, RotInputFileData, u_AD, u, p, p_AD, x
rMax = 0.0_ReKi
do k=1,p%numBlades
+ ! --- Curvilinear coordinates
+ ! TODO place this in a function
InitInp%zHub(k) = TwoNorm( u_AD%BladeRootMotion(k)%Position(:,1) - u_AD%HubMotion%Position(:,1) )
!if (EqualRealNos(InitInp%zHub(k),0.0_ReKi) ) &
! call SetErrStat( ErrID_Fatal, "zHub for blade "//trim(num2lstr(k))//" is zero.", ErrStat, ErrMsg, RoutineName)
@@ -4015,6 +4031,8 @@ SUBROUTINE Init_BEMTmodule( InputFileData, RotInputFileData, u_AD, u, p, p_AD, x
InitInp%zTip(k) = InitInp%zLocal(p%NumBlNds,k)
+ ! --- Projected radius onto plane normal to x_hat_disk
+ ! Note this is the same as local-polar radial position
y_hat_disk = u_AD%HubMotion%Orientation(2,:,1)
z_hat_disk = u_AD%HubMotion%Orientation(3,:,1)
@@ -4353,7 +4371,7 @@ SUBROUTINE TFin_CalcOutput(p, p_AD, u, m, y, ErrStat, ErrMsg )
force_tf(:) = 0.0_ReKi
moment_tf(:) = 0.0_ReKi
force_tf(1) = Cx * q
- force_tf(2) = Cy * q * p%TFin%TFinChord
+ force_tf(2) = Cy * q
force_tf(3) = 0.0_ReKi
moment_tf(1:2) = 0.0_ReKi
moment_tf(3) = AFI_interp%Cm * q * p%TFin%TFinChord
@@ -4628,13 +4646,16 @@ FUNCTION CalculateTowerInfluence(p, xbar_in, ybar, zbar, W_tower, TwrCd, TwrTI)
v_TwrPotent = ( -2.0*xbar * ybar ) / denom
elseif (p%TwrPotent == TwrPotent_Bak) then
- xbar = xbar + 0.1
+ ! Reference: Bak, Madsen, Johansen (2001): Influence from Blade-Tower Interaction on Fatigue Loads and Dynamics (poster);
+ ! Proceedings: EWEC'01; Copenhagen (DK)
+ xbar = xbar + 0.1 ! offset added as part of the original model of Bak et al.
denom = (xbar**2 + ybar**2)**2
u_TwrPotent = ( -1.0*xbar**2 + ybar**2 ) / denom
v_TwrPotent = ( -2.0*xbar * ybar ) / denom
denom = TwoPi*(xbar**2 + ybar**2)
u_TwrPotent = u_TwrPotent + TwrCd*xbar / denom
v_TwrPotent = v_TwrPotent + TwrCd*ybar / denom
+ xbar = xbar - 0.1 ! removing offset
end if
end if
diff --git a/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 b/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90
index 72a199cce9..1318ab04e2 100644
--- a/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90
+++ b/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90
@@ -35,78 +35,163 @@ MODULE AeroDyn_AllBldNdOuts_IO
! Blade:
- INTEGER(IntKi), PARAMETER :: BldNd_VUndx = 1
- INTEGER(IntKi), PARAMETER :: BldNd_VUndy = 2
- INTEGER(IntKi), PARAMETER :: BldNd_VUndz = 3
- INTEGER(IntKi), PARAMETER :: BldNd_Vundxi = 4
- INTEGER(IntKi), PARAMETER :: BldNd_Vundyi = 5
- INTEGER(IntKi), PARAMETER :: BldNd_Vundzi = 6
- INTEGER(IntKi), PARAMETER :: BldNd_VDisx = 7
- INTEGER(IntKi), PARAMETER :: BldNd_VDisy = 8
- INTEGER(IntKi), PARAMETER :: BldNd_VDisz = 9
- INTEGER(IntKi), PARAMETER :: BldNd_STVx = 10
- INTEGER(IntKi), PARAMETER :: BldNd_STVy = 11
- INTEGER(IntKi), PARAMETER :: BldNd_STVz = 12
- INTEGER(IntKi), PARAMETER :: BldNd_VRel = 13
- INTEGER(IntKi), PARAMETER :: BldNd_DynP = 14
- INTEGER(IntKi), PARAMETER :: BldNd_Re = 15
- INTEGER(IntKi), PARAMETER :: BldNd_M = 16
- INTEGER(IntKi), PARAMETER :: BldNd_Vindx = 17
- INTEGER(IntKi), PARAMETER :: BldNd_Vindy = 18
- INTEGER(IntKi), PARAMETER :: BldNd_AxInd = 19
- INTEGER(IntKi), PARAMETER :: BldNd_TnInd = 20
- INTEGER(IntKi), PARAMETER :: BldNd_Alpha = 21
- INTEGER(IntKi), PARAMETER :: BldNd_Theta = 22
- INTEGER(IntKi), PARAMETER :: BldNd_Phi = 23
- INTEGER(IntKi), PARAMETER :: BldNd_Curve = 24
- INTEGER(IntKi), PARAMETER :: BldNd_Cl = 25
- INTEGER(IntKi), PARAMETER :: BldNd_Cd = 26
- INTEGER(IntKi), PARAMETER :: BldNd_Cm = 27
- INTEGER(IntKi), PARAMETER :: BldNd_Cx = 28
- INTEGER(IntKi), PARAMETER :: BldNd_Cy = 29
- INTEGER(IntKi), PARAMETER :: BldNd_Cn = 30
- INTEGER(IntKi), PARAMETER :: BldNd_Ct = 31
- INTEGER(IntKi), PARAMETER :: BldNd_Fl = 32
- INTEGER(IntKi), PARAMETER :: BldNd_Fd = 33
- INTEGER(IntKi), PARAMETER :: BldNd_Mm = 34
- INTEGER(IntKi), PARAMETER :: BldNd_Fx = 35
- INTEGER(IntKi), PARAMETER :: BldNd_Fy = 36
- INTEGER(IntKi), PARAMETER :: BldNd_Fn = 37
- INTEGER(IntKi), PARAMETER :: BldNd_Ft = 38
- INTEGER(IntKi), PARAMETER :: BldNd_Clrnc = 39
- INTEGER(IntKi), PARAMETER :: BldNd_Vx = 40
- INTEGER(IntKi), PARAMETER :: BldNd_Vy = 41
- INTEGER(IntKi), PARAMETER :: BldNd_GeomPhi = 42
- INTEGER(IntKi), PARAMETER :: BldNd_Chi = 43
- INTEGER(IntKi), PARAMETER :: BldNd_UA_Flag = 44
- INTEGER(IntKi), PARAMETER :: BldNd_UA_x1 = 45
- INTEGER(IntKi), PARAMETER :: BldNd_UA_x2 = 46
- INTEGER(IntKi), PARAMETER :: BldNd_UA_x3 = 47
- INTEGER(IntKi), PARAMETER :: BldNd_UA_x4 = 48
- INTEGER(IntKi), PARAMETER :: BldNd_UA_x5 = 49
- INTEGER(IntKi), PARAMETER :: BldNd_Debug1 = 50
- INTEGER(IntKi), PARAMETER :: BldNd_Debug2 = 51
- INTEGER(IntKi), PARAMETER :: BldNd_Debug3 = 52
- INTEGER(IntKi), PARAMETER :: BldNd_CpMin = 53
- INTEGER(IntKi), PARAMETER :: BldNd_SgCav = 54
- INTEGER(IntKi), PARAMETER :: BldNd_SigCr = 55
- INTEGER(IntKi), PARAMETER :: BldNd_Gam = 56
- INTEGER(IntKi), PARAMETER :: BldNd_Cl_Static = 57
- INTEGER(IntKi), PARAMETER :: BldNd_Cd_Static = 58
- INTEGER(IntKi), PARAMETER :: BldNd_Cm_Static = 59
- INTEGER(IntKi), PARAMETER :: BldNd_Uin = 60
- INTEGER(IntKi), PARAMETER :: BldNd_Uit = 61
- INTEGER(IntKi), PARAMETER :: BldNd_Uir = 62
- INTEGER(IntKi), PARAMETER :: BldNd_Fbn = 63
- INTEGER(IntKi), PARAMETER :: BldNd_Fbt = 64
- INTEGER(IntKi), PARAMETER :: BldNd_Fbs = 65
- INTEGER(IntKi), PARAMETER :: BldNd_Mbn = 66
- INTEGER(IntKi), PARAMETER :: BldNd_Mbt = 67
- INTEGER(IntKi), PARAMETER :: BldNd_Mbs = 68
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndx = 1
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndy = 2
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndz = 3
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndxi = 4
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndyi = 5
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndzi = 6
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndxp = 7
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndyp = 8
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndzp = 9
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndxl = 10
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndyl = 11
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndzl = 12
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndxa = 13
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndya = 14
+ INTEGER(IntKi), PARAMETER :: BldNd_VUndza = 15
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisx = 16
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisy = 17
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisz = 18
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisxi = 19
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisyi = 20
+ INTEGER(IntKi), PARAMETER :: BldNd_VDiszi = 21
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisxp = 22
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisyp = 23
+ INTEGER(IntKi), PARAMETER :: BldNd_VDiszp = 24
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisxl = 25
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisyl = 26
+ INTEGER(IntKi), PARAMETER :: BldNd_VDiszl = 27
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisxa = 28
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisya = 29
+ INTEGER(IntKi), PARAMETER :: BldNd_VDisza = 30
+ INTEGER(IntKi), PARAMETER :: BldNd_STVx = 31
+ INTEGER(IntKi), PARAMETER :: BldNd_STVy = 32
+ INTEGER(IntKi), PARAMETER :: BldNd_STVz = 33
+ INTEGER(IntKi), PARAMETER :: BldNd_STVxi = 34
+ INTEGER(IntKi), PARAMETER :: BldNd_STVyi = 35
+ INTEGER(IntKi), PARAMETER :: BldNd_STVzi = 36
+ INTEGER(IntKi), PARAMETER :: BldNd_STVxp = 37
+ INTEGER(IntKi), PARAMETER :: BldNd_STVyp = 38
+ INTEGER(IntKi), PARAMETER :: BldNd_STVzp = 39
+ INTEGER(IntKi), PARAMETER :: BldNd_STVxl = 40
+ INTEGER(IntKi), PARAMETER :: BldNd_STVyl = 41
+ INTEGER(IntKi), PARAMETER :: BldNd_STVzl = 42
+ INTEGER(IntKi), PARAMETER :: BldNd_STVxa = 43
+ INTEGER(IntKi), PARAMETER :: BldNd_STVya = 44
+ INTEGER(IntKi), PARAMETER :: BldNd_STVza = 45
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindx = 46
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindy = 47
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindxi = 48
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindyi = 49
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindzi = 50
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindxp = 51
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindyp = 52
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindzp = 53
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindxl = 54
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindyl = 55
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindzl = 56
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindxa = 57
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindya = 58
+ INTEGER(IntKi), PARAMETER :: BldNd_Vindza = 59
+ INTEGER(IntKi), PARAMETER :: BldNd_Vx = 60
+ INTEGER(IntKi), PARAMETER :: BldNd_Vy = 61
+ INTEGER(IntKi), PARAMETER :: BldNd_VRel = 62
+ INTEGER(IntKi), PARAMETER :: BldNd_DynP = 63
+ INTEGER(IntKi), PARAMETER :: BldNd_Re = 64
+ INTEGER(IntKi), PARAMETER :: BldNd_M = 65
+ INTEGER(IntKi), PARAMETER :: BldNd_AxInd = 66
+ INTEGER(IntKi), PARAMETER :: BldNd_TnInd = 67
+ INTEGER(IntKi), PARAMETER :: BldNd_AxInd_qs = 68
+ INTEGER(IntKi), PARAMETER :: BldNd_TnInd_qs = 69
+ INTEGER(IntKi), PARAMETER :: BldNd_Alpha = 70
+ INTEGER(IntKi), PARAMETER :: BldNd_Phi = 71
+ INTEGER(IntKi), PARAMETER :: BldNd_Theta = 72
+ INTEGER(IntKi), PARAMETER :: BldNd_Curve = 73
+ INTEGER(IntKi), PARAMETER :: BldNd_Toe = 74
+ INTEGER(IntKi), PARAMETER :: BldNd_Cl = 75
+ INTEGER(IntKi), PARAMETER :: BldNd_Cd = 76
+ INTEGER(IntKi), PARAMETER :: BldNd_Cm = 77
+ INTEGER(IntKi), PARAMETER :: BldNd_Cx = 78
+ INTEGER(IntKi), PARAMETER :: BldNd_Cy = 79
+ INTEGER(IntKi), PARAMETER :: BldNd_Cn = 80
+ INTEGER(IntKi), PARAMETER :: BldNd_Ct = 81
+ INTEGER(IntKi), PARAMETER :: BldNd_Fxi = 82
+ INTEGER(IntKi), PARAMETER :: BldNd_Fyi = 83
+ INTEGER(IntKi), PARAMETER :: BldNd_Fzi = 84
+ INTEGER(IntKi), PARAMETER :: BldNd_Mxi = 85
+ INTEGER(IntKi), PARAMETER :: BldNd_Myi = 86
+ INTEGER(IntKi), PARAMETER :: BldNd_Mzi = 87
+ INTEGER(IntKi), PARAMETER :: BldNd_Fxp = 88
+ INTEGER(IntKi), PARAMETER :: BldNd_Fyp = 89
+ INTEGER(IntKi), PARAMETER :: BldNd_Fzp = 90
+ INTEGER(IntKi), PARAMETER :: BldNd_Mxp = 91
+ INTEGER(IntKi), PARAMETER :: BldNd_Myp = 92
+ INTEGER(IntKi), PARAMETER :: BldNd_Mzp = 93
+ INTEGER(IntKi), PARAMETER :: BldNd_Fxl = 94
+ INTEGER(IntKi), PARAMETER :: BldNd_Fyl = 95
+ INTEGER(IntKi), PARAMETER :: BldNd_Fzl = 96
+ INTEGER(IntKi), PARAMETER :: BldNd_Mxl = 97
+ INTEGER(IntKi), PARAMETER :: BldNd_Myl = 98
+ INTEGER(IntKi), PARAMETER :: BldNd_Mzl = 99
+ INTEGER(IntKi), PARAMETER :: BldNd_Fl = 100
+ INTEGER(IntKi), PARAMETER :: BldNd_Fd = 101
+ INTEGER(IntKi), PARAMETER :: BldNd_Mm = 102
+ INTEGER(IntKi), PARAMETER :: BldNd_Fx = 103
+ INTEGER(IntKi), PARAMETER :: BldNd_Fy = 104
+ INTEGER(IntKi), PARAMETER :: BldNd_Fn = 105
+ INTEGER(IntKi), PARAMETER :: BldNd_Ft = 106
+ INTEGER(IntKi), PARAMETER :: BldNd_Gam = 107
+ INTEGER(IntKi), PARAMETER :: BldNd_Clrnc = 108
+ INTEGER(IntKi), PARAMETER :: BldNd_GeomPhi = 109
+ INTEGER(IntKi), PARAMETER :: BldNd_Chi = 110
+ INTEGER(IntKi), PARAMETER :: BldNd_UA_Flag = 111
+ INTEGER(IntKi), PARAMETER :: BldNd_UA_x1 = 112
+ INTEGER(IntKi), PARAMETER :: BldNd_UA_x2 = 113
+ INTEGER(IntKi), PARAMETER :: BldNd_UA_x3 = 114
+ INTEGER(IntKi), PARAMETER :: BldNd_UA_x4 = 115
+ INTEGER(IntKi), PARAMETER :: BldNd_UA_x5 = 116
+ INTEGER(IntKi), PARAMETER :: BldNd_Debug1 = 117
+ INTEGER(IntKi), PARAMETER :: BldNd_Debug2 = 118
+ INTEGER(IntKi), PARAMETER :: BldNd_Debug3 = 119
+ INTEGER(IntKi), PARAMETER :: BldNd_CpMin = 120
+ INTEGER(IntKi), PARAMETER :: BldNd_SgCav = 121
+ INTEGER(IntKi), PARAMETER :: BldNd_SigCr = 122
+ INTEGER(IntKi), PARAMETER :: BldNd_BEM_F_qs = 123
+ INTEGER(IntKi), PARAMETER :: BldNd_BEM_k_qs = 124
+ INTEGER(IntKi), PARAMETER :: BldNd_BEM_kp_qs = 125
+ INTEGER(IntKi), PARAMETER :: BldNd_BEM_CT_qs = 126
+ INTEGER(IntKi), PARAMETER :: BldNd_Cl_qs = 127
+ INTEGER(IntKi), PARAMETER :: BldNd_Cd_qs = 128
+ INTEGER(IntKi), PARAMETER :: BldNd_Cm_qs = 129
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbxi = 130
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbyi = 131
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbzi = 132
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbxi = 133
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbyi = 134
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbzi = 135
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbxp = 136
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbyp = 137
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbzp = 138
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbxp = 139
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbyp = 140
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbzp = 141
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbxl = 142
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbyl = 143
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbzl = 144
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbxl = 145
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbyl = 146
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbzl = 147
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbxa = 148
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbya = 149
+ INTEGER(IntKi), PARAMETER :: BldNd_Fbza = 150
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbxa = 151
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbya = 152
+ INTEGER(IntKi), PARAMETER :: BldNd_Mbza = 153
! The maximum number of output channels which can be output by the code.
- INTEGER(IntKi), PARAMETER, PUBLIC :: BldNd_MaxOutPts = 68
+ INTEGER(IntKi), PARAMETER, PUBLIC :: BldNd_MaxOutPts = 153
!End of code generated by Matlab script Write_ChckOutLst
! ===================================================================================================
@@ -181,9 +266,9 @@ END SUBROUTINE AllBldNdOuts_InitOut
SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx, iRot, ErrStat, ErrMsg )
TYPE(RotParameterType), INTENT(IN ) :: p ! The rotor parameters
- TYPE(AD_ParameterType), INTENT(IN ) :: p_AD ! The module parameters
- TYPE(RotInputType), INTENT(IN ) :: u ! inputs
- TYPE(RotMiscVarType), INTENT(IN ) :: m ! misc variables
+ TYPE(AD_ParameterType),target,INTENT(IN ) :: p_AD ! The module parameters
+ TYPE(RotInputType), target, INTENT(IN ) :: u ! inputs
+ TYPE(RotMiscVarType), target, INTENT(IN ) :: m ! misc variables
TYPE(AD_MiscVarType), INTENT(IN ) :: m_AD ! misc variables ! NOTE: temporary
TYPE(RotContinuousStateType), INTENT(IN ) :: x ! rotor Continuous states
TYPE(RotOutputType), INTENT(INOUT) :: y ! outputs (updates y%WriteOutput)
@@ -195,20 +280,28 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
! local variables
- INTEGER(IntKi) :: OutIdx ! Index count within WriteOutput
- INTEGER(IntKi) :: IdxBlade, iW ! Counter to which blade we are on, and Wing
- INTEGER(IntKi) :: IdxNode ! Counter to the blade node we ae on
+ INTEGER(IntKi) :: iOut ! Index count within WriteOutput
+ INTEGER(IntKi) :: iB, iW ! Counter to which blade we are on, and Wing
+ INTEGER(IntKi) :: iNd ! Counter to the blade node we ae on
INTEGER(IntKi) :: IdxChan ! Counter to the channel we are outputting.
+ INTEGER(IntKi) :: nB, nNd ! number of blades, number of nodes
INTEGER(IntKi) :: compIndx ! index for array component (x,y,z)
CHARACTER(*), PARAMETER :: RoutineName = 'Calc_WriteAllBldNdOutput'
REAL(ReKi) :: ct, st ! cosine, sine of theta
REAL(ReKi) :: cp, sp ! cosine, sine of phi
- real(ReKi) :: M_ph(3,3) ! Transformation from hub to "blade-rotor-plane": n,t,r (not the same as AeroDyn)
- real(ReKi) :: M_pg(3,3,p%NumBlades) ! Transformation from global to "blade-rotor-plane" (n,t,r), with same x at hub coordinate system
+ real(ReKi) :: R_ph(3,3) ! Transformation from polar to hub (azimuth rotation along x hub)
+ real(ReKi) :: R_pi(3,3,p%NumBlades) ! Transformation from inertial to polar (same x at hub coordinate system, blade-azimuth rotated)
real(ReKi) :: psi_hub ! Azimuth wrt hub
- real(ReKi) :: Vind_g(3) ! Induced velocity vector in global coordinates
- real(ReKi) :: Vind_s(3) ! Induced velocity vector in section coordinates (AeroDyn "x-y")
-
+ real(R8Ki), dimension(:,:,:,:), pointer :: R_li ! Alias. Transformation from inertial to local-polar to airfoil (3x3xnNodesxnBlades)
+ real(R8Ki), dimension(:,:,:,:), pointer :: R_wi ! Alias. Transformation from inertial to "WithoutSweepPitchTwist" or "orientationAnnulus". TODO: deprecate me.
+ integer(Intki), dimension(:) , pointer :: W2B ! Alias. Index from Wing index to Blade
+
+ ! Alias to shorten notations
+ nB = p%BldNd_BladesOut
+ nNd = p%NumBlNds
+ R_li => m%R_li ! inertial to local-polar
+ R_wi => m%orientationAnnulus ! inertial to without-sweep-pitch-twist or orientation annulus (TODO: deprecate me)
+ W2B => p_AD%FVW%Bld2Wings(iRot, :) ! From Wing index to blade index
! Initialize some things
ErrMsg = ''
@@ -218,20 +311,18 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
return
endif
-
- ! Precalculate the M_ph matrix -- no reason to recalculate for each output
- DO IdxBlade=1,p%NumBlades
- psi_hub = TwoPi*(real(IdxBlade-1,ReKi))/real(p%NumBlades,ReKi)
- M_ph(1,1:3) = (/ 1.0_ReKi, 0.0_ReKi , 0.0_ReKi /)
- M_ph(2,1:3) = (/ 0.0_ReKi, cos(psi_hub), sin(psi_hub) /)
- M_ph(3,1:3) = (/ 0.0_ReKi,-sin(psi_hub), cos(psi_hub) /)
- M_pg(1:3,1:3,IdxBlade) = matmul(M_ph, u%HubMotion%Orientation(1:3,1:3,1) )
- ENDDO
-
+ ! Precalculate the R_pi matrix -- no reason to recalculate for each output
+ do iB=1,p%NumBlades
+ psi_hub = TwoPi*(real(iB-1,ReKi))/real(p%NumBlades,ReKi)
+ R_ph(1,1:3) = (/ 1.0_ReKi, 0.0_ReKi , 0.0_ReKi /)
+ R_ph(2,1:3) = (/ 0.0_ReKi, cos(psi_hub), sin(psi_hub) /)
+ R_ph(3,1:3) = (/ 0.0_ReKi,-sin(psi_hub), cos(psi_hub) /)
+ R_pi(1:3,1:3,iB) = matmul(R_ph, u%HubMotion%Orientation(1:3,1:3,1) )
+ enddo
! Populate the header an unit lines for all blades and nodes
! First set a counter so we know where in the output array we are in
- OutIdx = p%NumOuts + 1 ! p%NumOuts is the number of outputs from the normal AeroDyn output. The WriteOutput array is sized to p%NumOuts + num(AllBldNdOuts)
+ iOut = p%NumOuts + 1 ! p%NumOuts is the number of outputs from the normal AeroDyn output. The WriteOutput array is sized to p%NumOuts + num(AllBldNdOuts)
! Case to assign output to this channel and populate based on Indx value (this indicates what the channel is)
@@ -239,138 +330,150 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
DO IdxChan=1,p%BldNd_NumOuts
SELECT CASE( p%BldNd_OutParam(IdxChan)%Indx ) ! Indx contains the information on what channel should be output
- CASE (0) ! Invalid channel
- ! We still have headers for invalid channels. Need to account for that
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- ! ***** Undisturbed wind velocity in local blade coord system *****
- CASE ( BldNd_VUndx )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(1,:,IdxNode,IdxBlade), u%InflowOnBlade(:,IdxNode,IdxBlade) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
-
- CASE ( BldNd_VUndy )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(2,:,IdxNode,IdxBlade), u%InflowOnBlade(:,IdxNode,IdxBlade) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_VUndz )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(3,:,IdxNode,IdxBlade), u%InflowOnBlade(:,IdxNode,IdxBlade) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
-
- ! ***** Undisturbed wind velocity in inertial/global coord system *****
- CASE ( BldNd_VUndxi )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = u%InflowOnBlade(1,IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- END DO
- END DO
-
-
- CASE ( BldNd_VUndyi )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = u%InflowOnBlade(2,IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_VUndzi )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = u%InflowOnBlade(3,IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- END DO
- END DO
-
-
+ ! Invalid channel, we still have headers for invalid channels. Need to account for that
+ CASE (0 ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = 0.0_ReKi; iOut = iOut + 1; enddo;enddo
- ! ***** Disturbed wind velocity in the local blade coordinate system *****
- CASE ( BldNd_VDisx )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(1,:,IdxNode,IdxBlade), m%DisturbedInflow(:,IdxNode,IdxBlade) )
- OutIdx = OutIdx + 1
- END DO
- END DO
+ ! ***** Undisturbed wind velocity in inertial, polar, local and airfoil systems*****
+ CASE( BldNd_VUndxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = u%InflowOnBlade(1,iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndyi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = u%InflowOnBlade(2,iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndzi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = u%InflowOnBlade(3,iNd,iB); iOut = iOut + 1; enddo;enddo
- CASE ( BldNd_VDisy )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(2,:,IdxNode,IdxBlade), m%DisturbedInflow(:,IdxNode,IdxBlade) )
- OutIdx = OutIdx + 1
- END DO
- END DO
+ CASE( BldNd_VUndxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_pi(1,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndyp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_pi(2,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndzp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_pi(3,:,iB) ); iOut = iOut + 1; enddo;enddo
- CASE ( BldNd_VDisz )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(3,:,IdxNode,IdxBlade), m%DisturbedInflow(:,IdxNode,IdxBlade) )
- OutIdx = OutIdx + 1
- END DO
- END DO
+ CASE( BldNd_VUndxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_li(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndyl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_li(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndzl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_li(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
-
- ! ***** Structural translational velocity in the local blade coordinate system *****
- CASE ( BldNd_STVx )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(1,:,IdxNode,IdxBlade), u%BladeMotion(IdxBlade)%TranslationVel(:,IdxNode) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_STVy )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(2,:,IdxNode,IdxBlade), u%BladeMotion(IdxBlade)%TranslationVel(:,IdxNode) )
- OutIdx = OutIdx + 1
+ CASE( BldNd_VUndxa ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), u%BladeMotion(iB)%Orientation(1,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndya ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), u%BladeMotion(iB)%Orientation(2,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndza ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), u%BladeMotion(iB)%Orientation(3,:,iNd) ); iOut = iOut + 1; enddo;enddo
+
+ ! TODO: deprecate this
+ CASE( BldNd_VUndx ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_wi(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndy ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_wi(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VUndz ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%InflowOnBlade(:,iNd,iB), R_wi(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+
+
+ ! ***** Disturbed wind velocity in inertial, polar, local and airfoil systems*****
+ CASE( BldNd_VDisxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%DisturbedInflow(1,iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDisyi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%DisturbedInflow(2,iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDiszi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%DisturbedInflow(3,iNd,iB); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_VDisxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_pi(1,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDisyp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_pi(2,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDiszp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_pi(3,:,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_VDisxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_li(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDisyl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_li(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDiszl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_li(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_VDisxa ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), u%BladeMotion(iB)%Orientation(1,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDisya ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), u%BladeMotion(iB)%Orientation(2,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDisza ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), u%BladeMotion(iB)%Orientation(3,:,iNd) ); iOut = iOut + 1; enddo;enddo
+
+ ! TODO: deprecate this
+ CASE( BldNd_VDisx ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_wi(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDisy ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_wi(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_VDisz ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%DisturbedInflow(:,iNd,iB), R_wi(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+
+
+ ! ***** Structural translational velocity inertial, polar, local and airfoil systems*****
+ CASE( BldNd_STVxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = u%BladeMotion(iB)%TranslationVel(1,iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVyi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = u%BladeMotion(iB)%TranslationVel(2,iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVzi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = u%BladeMotion(iB)%TranslationVel(3,iNd); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_STVxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_pi(1,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVyp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_pi(2,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVzp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_pi(3,:,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_STVxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_li(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVyl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_li(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVzl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_li(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_STVxa ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), u%BladeMotion(iB)%Orientation(1,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVya ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), u%BladeMotion(iB)%Orientation(2,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVza ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), u%BladeMotion(iB)%Orientation(3,:,iNd) ); iOut = iOut + 1; enddo;enddo
+
+ ! TODO: deprecate this
+ CASE( BldNd_STVx ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_wi(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVy ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_wi(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_STVz ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( u%BladeMotion(iB)%TranslationVel(:,iNd), R_wi(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+
+ ! ***** Induced velocities in inertial, polar, local and airfoil systems*****
+ ! Axial and tangential induced wind velocity
+ ! TODO use m%Vind_i and R_wi
+ CASE ( BldNd_Vindx )
+ if (p_AD%WakeMod /= WakeMod_FVW) then
+ do iB=1,nB
+ do iNd=1,nNd
+ y%WriteOutput(iOut) = - m%BEMT_u(Indx)%Vx(iNd,iB) * m%BEMT_y%axInduction( iNd,iB)
+ iOut = iOut + 1
+ enddo
+ enddo
+ else
+ do iB=1,nB
+ iW = W2B(iB)
+ do iNd=1,nNd;
+ y%WriteOutput(iOut) = -m_AD%FVW%W(iW)%BN_UrelWind_s(1,iNd) * m_AD%FVW%W(iW)%BN_AxInd(iNd)
+ iOut = iOut + 1
+ enddo
+ enddo
+ endif
+
+ CASE ( BldNd_Vindy )
+ if (p_AD%WakeMod /= WakeMod_FVW) then
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_u(Indx)%Vy(iNd,iB) * m%BEMT_y%tanInduction(iNd,iB)
+ iOut = iOut + 1
+ END DO
END DO
- END DO
-
- CASE ( BldNd_STVz )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( m%orientationAnnulus(3,:,IdxNode,IdxBlade), u%BladeMotion(IdxBlade)%TranslationVel(:,IdxNode) )
- OutIdx = OutIdx + 1
+ else
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_UrelWind_s(2,iNd) * m_AD%FVW%W(iW)%BN_TanInd(iNd)
+ iOut = iOut + 1
+ END DO
END DO
- END DO
+ endif
+
+ CASE( BldNd_Vindxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%Vind_i(1, iNd, iB); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindyi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%Vind_i(2, iNd, iB); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindzi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%Vind_i(3, iNd, iB); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Vindxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), R_pi(1,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindyp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), R_pi(2,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindzp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), R_pi(3,:,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Vindxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), R_li(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindyl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), R_li(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindzl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), R_li(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Vindxa ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), u%BladeMotion(iB)%Orientation(1,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindya ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), u%BladeMotion(iB)%Orientation(2,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Vindza ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%Vind_i(:, iNd, iB), u%BladeMotion(iB)%Orientation(3,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ ! TODO: Vrel, DynP, Re, Ma - should be unified across lifting-line implementations. Vrel should be computed based on velocities in (a)-system
! Relative wind speed
CASE ( BldNd_VRel )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%Vrel(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%Vrel(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Vrel(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Vrel(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
@@ -378,18 +481,18 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
! Dynamic pressure
CASE ( BldNd_DynP )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = 0.5 * p%airDens * m%BEMT_y%Vrel(IdxNode,IdxBlade)**2
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = 0.5 * p%airDens * m%BEMT_y%Vrel(iNd,iB)**2
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = 0.5 * p%airDens * m_AD%FVW%W(iW)%BN_Vrel(IdxNode)**2
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = 0.5 * p%airDens * m_AD%FVW%W(iW)%BN_Vrel(iNd)**2
+ iOut = iOut + 1
END DO
END DO
endif
@@ -397,18 +500,18 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
! Reynolds number (in millions)
CASE ( BldNd_Re )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = p%BEMT%chord(IdxNode,IdxBlade) * m%BEMT_y%Vrel(IdxNode,IdxBlade) / p%KinVisc / 1.0E6
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = p%BEMT%chord(iNd,iB) * m%BEMT_y%Vrel(iNd,iB) / p%KinVisc / 1.0E6
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Re(IdxNode) / 1.0E6
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Re(iNd) / 1.0E6
+ iOut = iOut + 1
END DO
END DO
endif
@@ -416,263 +519,282 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
! Mach number
CASE ( BldNd_M )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%Vrel(IdxNode,IdxBlade) / p%SpdSound
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%Vrel(iNd,iB) / p%SpdSound
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Vrel(IdxNode) / p%SpdSound
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Vrel(iNd) / p%SpdSound
+ iOut = iOut + 1
END DO
END DO
endif
-
-
- ! Axial and tangential induced wind velocity
- CASE ( BldNd_Vindx )
+
+ ! Axial and tangential induction factors
+ CASE ( BldNd_AxInd )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = - m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade) * m%BEMT_y%axInduction( IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%axInduction(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = -m_AD%FVW%W(iW)%BN_UrelWind_s(1,IdxNode) * m_AD%FVW%W(iW)%BN_AxInd(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_AxInd(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
-
- CASE ( BldNd_Vindy )
+
+ CASE ( BldNd_TnInd )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade) * m%BEMT_y%tanInduction(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%tanInduction(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_UrelWind_s(2,IdxNode) * m_AD%FVW%W(iW)%BN_TanInd(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_TanInd(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
-
- ! Axial and tangential induction factors
- CASE ( BldNd_AxInd )
+ ! Quasi-steady Axial and tangential induction factors
+ CASE ( BldNd_AxInd_qs )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%axInduction(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%axInduction_qs(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_AxInd(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_AxInd(iNd) ! TODO
+ iOut = iOut + 1
END DO
END DO
endif
- CASE ( BldNd_TnInd )
+ CASE ( BldNd_TnInd_qs )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%tanInduction(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%tanInduction_qs(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_TanInd(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_TanInd(iNd) ! TODO
+ iOut = iOut + 1
END DO
END DO
endif
-
+
! AoA, pitch+twist angle, inflow angle, and curvature angle
CASE ( BldNd_Alpha )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = Rad2M180to180Deg( m%BEMT_y%phi(IdxNode,IdxBlade) - m%BEMT_u(Indx)%theta(IdxNode,IdxBlade) )
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ ! TODO Change this
+ y%WriteOutput(iOut) = Rad2M180to180Deg( m%BEMT_y%phi(iNd,iB) - m%BEMT_u(Indx)%theta(iNd,iB) )
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_alpha(IdxNode)*R2D
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_alpha(iNd)*R2D
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Theta )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%theta(IdxNode,IdxBlade)*R2D
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_u(Indx)%theta(iNd,iB)*R2D
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)*R2D
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%PitchAndTwist(iNd)*R2D
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Phi )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%phi(IdxNode,IdxBlade)*R2D
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%phi(iNd,iB)*R2D
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) =m_AD%FVW%W(iW)%BN_phi(IdxNode)*R2D
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) =m_AD%FVW%W(iW)%BN_phi(iNd)*R2D
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Curve )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%Curve(IdxNode,IdxBlade)*R2D
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%Curve(iNd,iB)*R2D
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
!NOT available in FVW yet
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
+ END DO
+ END DO
+ endif
+
+ CASE ( BldNd_Toe )
+ if (p_AD%WakeMod /= WakeMod_FVW) then
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_u(Indx)%toeAngle(iNd,iB)*R2D
+ iOut = iOut + 1
+ END DO
+ END DO
+ else
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
END DO
END DO
endif
- ! Lift force, drag force, pitching moment coefficients
+ ! Unsteady lift force, drag force, pitching moment coefficients
+ ! TODO this should be somehow unified across lifting-line implementations
CASE ( BldNd_Cl )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%Cl(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%Cl(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cl(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cl(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Cd )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%Cd(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%Cd(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cd(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cd(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Cm )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%Cm(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%Cm(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cm(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cm(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
! Normal force (to plane), tangential force (to plane) coefficients
+ ! TODO deprecate
CASE ( BldNd_Cx )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%Cx(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%Cx(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cx(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cx(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Cy )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%Cy(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%Cy(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cy(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cy(iNd)
+ iOut = iOut + 1
END DO
END DO
endif
@@ -680,44 +802,44 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
! Normal force (to chord), and tangential force (to chord) coefficients
CASE ( BldNd_Cn )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = m%BEMT_y%Cx(IdxNode,IdxBlade)*ct + m%BEMT_y%Cy(IdxNode,IdxBlade)*st
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ ct=cos(m%BEMT_u(Indx)%theta(iNd,iB))
+ st=sin(m%BEMT_u(Indx)%theta(iNd,iB))
+ y%WriteOutput(iOut) = m%BEMT_y%Cx(iNd,iB)*ct + m%BEMT_y%Cy(iNd,iB)*st
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! cos(theta)
- st=sin(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! sin(theta)
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cx(IdxNode)*ct + m_AD%FVW%W(iW)%BN_Cy(IdxNode)*st
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! cos(theta)
+ st=sin(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! sin(theta)
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cx(iNd)*ct + m_AD%FVW%W(iW)%BN_Cy(iNd)*st
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Ct )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = -m%BEMT_y%Cx(IdxNode,IdxBlade)*st + m%BEMT_y%Cy(IdxNode,IdxBlade)*ct
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ ct=cos(m%BEMT_u(Indx)%theta(iNd,iB))
+ st=sin(m%BEMT_u(Indx)%theta(iNd,iB))
+ y%WriteOutput(iOut) = -m%BEMT_y%Cx(iNd,iB)*st + m%BEMT_y%Cy(iNd,iB)*ct
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! cos(theta)
- st=sin(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! sin(theta)
- y%WriteOutput( OutIdx ) = -m_AD%FVW%W(iW)%BN_Cx(IdxNode)*st + m_AD%FVW%W(iW)%BN_Cy(IdxNode)*ct
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! cos(theta)
+ st=sin(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! sin(theta)
+ y%WriteOutput(iOut) = -m_AD%FVW%W(iW)%BN_Cx(iNd)*st + m_AD%FVW%W(iW)%BN_Cy(iNd)*ct
+ iOut = iOut + 1
END DO
END DO
endif
@@ -726,169 +848,181 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
! Lift force, drag force, pitching moment
CASE ( BldNd_Fl )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- cp=cos(m%BEMT_y%phi(IdxNode,IdxBlade))
- sp=sin(m%BEMT_y%phi(IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*cp - m%Y(IdxNode,IdxBlade)*sp
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ cp=cos(m%BEMT_y%phi(iNd,iB))
+ sp=sin(m%BEMT_y%phi(iNd,iB))
+ y%WriteOutput(iOut) = m%X(iNd,iB)*cp - m%Y(iNd,iB)*sp
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- cp=cos(m_AD%FVW%W(iW)%BN_phi(IdxNode))
- sp=sin(m_AD%FVW%W(iW)%BN_phi(IdxNode))
- y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*cp - m%Y(IdxNode,IdxBlade)*sp
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ cp=cos(m_AD%FVW%W(iW)%BN_phi(iNd))
+ sp=sin(m_AD%FVW%W(iW)%BN_phi(iNd))
+ y%WriteOutput(iOut) = m%X(iNd,iB)*cp - m%Y(iNd,iB)*sp
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Fd )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- cp=cos(m%BEMT_y%phi(IdxNode,IdxBlade))
- sp=sin(m%BEMT_y%phi(IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*sp + m%Y(IdxNode,IdxBlade)*cp
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ cp=cos(m%BEMT_y%phi(iNd,iB))
+ sp=sin(m%BEMT_y%phi(iNd,iB))
+ y%WriteOutput(iOut) = m%X(iNd,iB)*sp + m%Y(iNd,iB)*cp
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- cp=cos(m_AD%FVW%W(iW)%BN_phi(IdxNode))
- sp=sin(m_AD%FVW%W(iW)%BN_phi(IdxNode))
- y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*sp + m%Y(IdxNode,IdxBlade)*cp
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ cp=cos(m_AD%FVW%W(iW)%BN_phi(iNd))
+ sp=sin(m_AD%FVW%W(iW)%BN_phi(iNd))
+ y%WriteOutput(iOut) = m%X(iNd,iB)*sp + m%Y(iNd,iB)*cp
+ iOut = iOut + 1
END DO
END DO
endif
- CASE ( BldNd_Mm )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%M(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- ! Normal force (to plane), tangential force (to plane)
- CASE ( BldNd_Fx )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- END DO
- END DO
+ CASE ( BldNd_Mm ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%M(iNd,iB); iOut = iOut + 1; enddo;enddo
- CASE ( BldNd_Fy )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = -m%Y(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- END DO
- END DO
+ ! Normal force (to plane), tangential force (to plane)
+ ! TODO deprecate
+ CASE ( BldNd_Fx ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%X(iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE ( BldNd_Fy ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = -m%Y(iNd,iB); iOut = iOut + 1; enddo;enddo
! Normal force (to chord), and tangential force (to chord) per unit length
+ !CASE( BldNd_Fn ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), u%BladeMotion(iB)%Orientation(1,:,iNd)); iOut = iOut + 1; enddo;enddo
CASE ( BldNd_Fn )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*ct - m%Y(IdxNode,IdxBlade)*st
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ ct=cos(m%BEMT_u(Indx)%theta(iNd,iB))
+ st=sin(m%BEMT_u(Indx)%theta(iNd,iB))
+ y%WriteOutput(iOut) = m%X(iNd,iB)*ct - m%Y(iNd,iB)*st
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! cos(theta)
- st=sin(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! sin(theta)
- y%WriteOutput( OutIdx ) = m%X(IdxNode,IdxBlade)*ct - m%Y(IdxNode,IdxBlade)*st
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! cos(theta)
+ st=sin(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! sin(theta)
+ y%WriteOutput(iOut) = m%X(iNd,iB)*ct - m%Y(iNd,iB)*st
+ iOut = iOut + 1
END DO
END DO
endif
+ !CASE( BldNd_Ft ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = -dot_product( y%BladeLoad(iB)%Force (:, iNd), u%BladeMotion(iB)%Orientation(2,:,iNd)); iOut = iOut + 1; enddo;enddo
CASE ( BldNd_Ft )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- ct=cos(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- st=sin(m%BEMT_u(Indx)%theta(IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = -m%X(IdxNode,IdxBlade)*st - m%Y(IdxNode,IdxBlade)*ct
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ ct=cos(m%BEMT_u(Indx)%theta(iNd,iB))
+ st=sin(m%BEMT_u(Indx)%theta(iNd,iB))
+ y%WriteOutput(iOut) = -m%X(iNd,iB)*st - m%Y(iNd,iB)*ct
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! cos(theta)
- st=sin(m_AD%FVW%W(iW)%PitchAndTwist(IdxNode)) ! sin(theta)
- y%WriteOutput( OutIdx ) = -m%X(IdxNode,IdxBlade)*st - m%Y(IdxNode,IdxBlade)*ct
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ ct=cos(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! cos(theta)
+ st=sin(m_AD%FVW%W(iW)%PitchAndTwist(iNd)) ! sin(theta)
+ y%WriteOutput(iOut) = -m%X(iNd,iB)*st - m%Y(iNd,iB)*ct
+ iOut = iOut + 1
END DO
END DO
endif
- ! Tower clearance (requires tower influence calculation):
+ ! ******* Force/Moment in: global, polar, local-polar and airfoil system
+ CASE( BldNd_Fxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = y%BladeLoad(iB)%Force (1, iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fyi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = y%BladeLoad(iB)%Force (2, iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fzi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = y%BladeLoad(iB)%Force (3, iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = y%BladeLoad(iB)%Moment(1, iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Myi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = y%BladeLoad(iB)%Moment(2, iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mzi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = y%BladeLoad(iB)%Moment(3, iNd); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Fxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), R_pi(1,:,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fyp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), R_pi(2,:,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fzp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), R_pi(3,:,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Moment(:, iNd), R_pi(1,:,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Myp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Moment(:, iNd), R_pi(2,:,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mzp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Moment(:, iNd), R_pi(3,:,iB)); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Fxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), R_li(1,:,iNd,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fyl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), R_li(2,:,iNd,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fzl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), R_li(3,:,iNd,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Moment(:, iNd), R_li(1,:,iNd,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Myl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Moment(:, iNd), R_li(2,:,iNd,iB)); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mzl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Moment(:, iNd), R_li(3,:,iNd,iB)); iOut = iOut + 1; enddo;enddo
+
+ ! NOTE: BldNd_Fn=BldNd_Fxa, BldNd_Ft=-BldNd_Fya (minus sign!), BldNd_Mm=BldNd_Mza BldNdMxa=0
+ !CASE( BldNd_Fxa ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), u%BladeMotion(iB)%Orientation(1,:,iNd)); iOut = iOut + 1; enddo;enddo
+ !CASE( BldNd_Fya ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Force (:, iNd), u%BladeMotion(iB)%Orientation(2,:,iNd)); iOut = iOut + 1; enddo;enddo
+ !CASE( BldNd_Mza ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( y%BladeLoad(iB)%Moment(:, iNd), u%BladeMotion(iB)%Orientation(3,:,iNd)); iOut = iOut + 1; enddo;enddo
+
+ ! Tower clearance (requires tower influence calculation):
CASE ( BldNd_Clrnc )
if (.not. allocated(m%TwrClrnc)) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%TwrClrnc(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%TwrClrnc(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
end if
+ ! TODO: remove me, Vx, Vy can be computed from other outputs (and they are in legacy coordinate system)
CASE ( BldNd_Vx )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_u(Indx)%Vx(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_UrelWind_s(1,IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_UrelWind_s(1,iNd)
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_Vy )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_u(Indx)%Vy(iNd,iB)
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_UrelWind_s(2,IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_UrelWind_s(2,iNd)
+ iOut = iOut + 1
END DO
END DO
endif
@@ -896,48 +1030,48 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
CASE ( BldNd_GeomPhi )
if (p_AD%WakeMod /= WakeMod_FVW) then
if (allocated(OtherState%BEMT%ValidPhi)) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- if (OtherState%BEMT%ValidPhi(IdxNode,IdxBlade)) then
- y%WriteOutput( OutIdx ) = 1.0_ReKi - m%BEMT%BEM_weight
+ DO iB=1,nB
+ DO iNd=1,nNd
+ if (OtherState%BEMT%ValidPhi(iNd,iB)) then
+ y%WriteOutput(iOut) = 1.0_ReKi - m%BEMT%BEM_weight
else
- y%WriteOutput( OutIdx ) = 1.0_ReKi
+ y%WriteOutput(iOut) = 1.0_ReKi
end if
- OutIdx = OutIdx + 1
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = 1.0_ReKi
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = 1.0_ReKi
+ iOut = iOut + 1
END DO
END DO
end if
else
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = 0.0_ReKi ! Not valid for FVW
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = 0.0_ReKi ! Not valid for FVW
+ iOut = iOut + 1
END DO
END DO
endif
CASE ( BldNd_chi )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = m%BEMT_y%chi(IdxNode,IdxBlade)*R2D
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,nNd
+ y%WriteOutput(iOut) = m%BEMT_y%chi(iNd,iB)*R2D
+ iOut = iOut + 1
END DO
END DO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
+ DO iB=1,nB
+ DO iNd=1,nNd
!NOT available in FVW yet
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
END DO
END DO
endif
@@ -945,26 +1079,26 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
CASE ( BldNd_UA_Flag )
IF (p_AD%UA_Flag) THEN
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m%BEMT%UA%weight(IdxNode, IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = m%BEMT%UA%weight(iNd, iB)
+ iOut = iOut + 1
ENDDO
ENDDO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%m_UA%weight(IdxNode, 1)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%m_UA%weight(iNd, 1)
+ iOut = iOut + 1
ENDDO
ENDDO
end if
ELSE
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
ENDDO
ENDDO
END IF
@@ -986,291 +1120,187 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx
END SELECT
!if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = x%BEMT%UA%element(IdxNode, IdxBlade)%x(compIndx)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = x%BEMT%UA%element(iNd, iB)%x(compIndx)
+ iOut = iOut + 1
ENDDO
ENDDO
!else
- ! DO IdxBlade=1,p%BldNd_BladesOut
- ! iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- ! DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- ! y%WriteOutput( OutIdx ) = x_AD%FVW%UA(iW)%element(IdxNode, IdxBlade)%x(compIndx)
- ! OutIdx = OutIdx + 1
+ ! DO iB=1,nB
+ ! iW = W2B(iB)
+ ! DO iNd=1,u%BladeMotion(iB)%NNodes
+ ! y%WriteOutput(iOut) = x_AD%FVW%UA(iW)%element(iNd, iB)%x(compIndx)
+ ! iOut = iOut + 1
! ENDDO
! ENDDO
!end if
ELSE
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
ENDDO
ENDDO
END IF
-
- CASE ( BldNd_Debug1 )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = 0.0_ReKi ! something here
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_Debug2 )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = 0.0_ReKi ! something here
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_Debug3 )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = 0.0_ReKi ! something here
- OutIdx = OutIdx + 1
- END DO
- END DO
-
! CpMin
CASE ( BldNd_CpMin )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m%BEMT_y%Cpmin(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = m%BEMT_y%Cpmin(iNd,iB)
+ iOut = iOut + 1
ENDDO
ENDDO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cpmin(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cpmin(iNd)
+ iOut = iOut + 1
ENDDO
ENDDO
endif
! Cavitation
- CASE ( BldNd_SgCav )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m%SigmaCavit(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
-
- CASE ( BldNd_SigCr )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m%SigmaCavitCrit(IdxNode,IdxBlade)
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
+ CASE ( BldNd_SgCav ); do iB=1,nB; do iNd=1,u%BladeMotion(iB)%NNodes; y%WriteOutput(iOut) = m%SigmaCavit(iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE ( BldNd_SigCr ); do iB=1,nB; do iNd=1,u%BladeMotion(iB)%NNodes; y%WriteOutput(iOut) = m%SigmaCavitCrit(iNd,iB); iOut = iOut + 1; enddo;enddo
! circulation on blade
CASE ( BldNd_Gam )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = 0.5_ReKi * p%BEMT%chord(IdxNode,IdxBlade) * m%BEMT_y%Vrel(IdxNode,IdxBlade) * m%BEMT_y%Cl(IdxNode,IdxBlade) ! "Gam" [m^2/s]
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = 0.5_ReKi * p%BEMT%chord(iNd,iB) * m%BEMT_y%Vrel(iNd,iB) * m%BEMT_y%Cl(iNd,iB) ! "Gam" [m^2/s]
+ iOut = iOut + 1
ENDDO
ENDDO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = 0.5_ReKi * p_AD%FVW%W(iW)%chord_LL(IdxNode) * m_AD%FVW%W(iW)%BN_Vrel(IdxNode) * m_AD%FVW%W(iW)%BN_Cl(IdxNode) ! "Gam" [m^2/s]
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = 0.5_ReKi * p_AD%FVW%W(iW)%chord_LL(iNd) * m_AD%FVW%W(iW)%BN_Vrel(iNd) * m_AD%FVW%W(iW)%BN_Cl(iNd) ! "Gam" [m^2/s]
+ iOut = iOut + 1
ENDDO
ENDDO
endif
- !================================================
- ! Static portion of Cl, Cd, Cm (ignoring unsteady effects)
- ! Cl_Static
- CASE ( BldNd_Cl_Static )
+ !================================================ OLAF ONLY
+ ! Static portion of Cl, Cd, Cm (ignoring unsteady effects)
+ ! TODO this should be provided by all lifting-line codes
+ ! Cl_Static
+ CASE ( BldNd_Cl_qs )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
!NOT available in BEMT/DBEMT yet
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
ENDDO
ENDDO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cl_Static(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cl_Static(iNd)
+ iOut = iOut + 1
ENDDO
ENDDO
endif
! Cd_Static
- CASE ( BldNd_Cd_Static )
+ CASE ( BldNd_Cd_qs )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
!NOT available in BEMT/DBEMT yet
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
ENDDO
ENDDO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cd_Static(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cd_Static(iNd)
+ iOut = iOut + 1
ENDDO
ENDDO
endif
! Cm_Static
- CASE ( BldNd_Cm_Static )
+ CASE ( BldNd_Cm_qs )
if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
+ DO iB=1,nB
+ DO iNd=1,u%BladeMotion(iB)%NNodes
!NOT available in BEMT/DBEMT yet
- y%WriteOutput( OutIdx ) = 0.0_ReKi
- OutIdx = OutIdx + 1
+ y%WriteOutput(iOut) = 0.0_ReKi
+ iOut = iOut + 1
ENDDO
ENDDO
else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = m_AD%FVW%W(iW)%BN_Cm_Static(IdxNode)
- OutIdx = OutIdx + 1
+ DO iB=1,nB
+ iW = W2B(iB)
+ DO iNd=1,u%BladeMotion(iB)%NNodes
+ y%WriteOutput(iOut) = m_AD%FVW%W(iW)%BN_Cm_Static(iNd)
+ iOut = iOut + 1
ENDDO
ENDDO
endif
-
-
- !================================================
- ! Inductions in polar rotating hub coordinates
- ! Axial induction, polar rotating hub coordinates
- CASE ( BldNd_Uin )
- if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- Vind_s = (/ -m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade)*m%BEMT_y%axInduction(IdxNode,IdxBlade), m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade)*m%BEMT_y%tanInduction(IdxNode,IdxBlade), 0.0_ReKi /)
- Vind_g = matmul(Vind_s, m%orientationAnnulus(:,:,IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = dot_product(M_pg(1,1:3,IdxBlade), Vind_g(1:3) ) ! Uihn, hub normal
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
- else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = dot_product(M_pg(1,1:3,IdxBlade), m_AD%FVW_y%W(iW)%Vind(1:3,IdxNode) ) ! Uihn, hub normal
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
- endif
-
- ! Tangential induction, polar rotating hub coordinates
- CASE ( BldNd_Uit )
- if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- Vind_s = (/ -m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade)*m%BEMT_y%axInduction(IdxNode,IdxBlade), m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade)*m%BEMT_y%tanInduction(IdxNode,IdxBlade), 0.0_ReKi /)
- Vind_g = matmul(Vind_s, m%orientationAnnulus(:,:,IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = dot_product(M_pg(2,1:3,IdxBlade), Vind_g(1:3) ) ! Uiht, hub tangential
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
- else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = dot_product(M_pg(2,1:3,IdxBlade), m_AD%FVW_y%W(iW)%Vind(1:3,IdxNode) ) ! Uiht, hub tangential
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
- endif
-
- ! Radial induction, polar rotating hub coordinates
- CASE ( BldNd_Uir )
- if (p_AD%WakeMod /= WakeMod_FVW) then
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- Vind_s = (/ -m%BEMT_u(Indx)%Vx(IdxNode,IdxBlade)*m%BEMT_y%axInduction(IdxNode,IdxBlade), m%BEMT_u(Indx)%Vy(IdxNode,IdxBlade)*m%BEMT_y%tanInduction(IdxNode,IdxBlade), 0.0_ReKi /)
- Vind_g = matmul(Vind_s, m%orientationAnnulus(:,:,IdxNode,IdxBlade))
- y%WriteOutput( OutIdx ) = dot_product(M_pg(3,1:3,IdxBlade), Vind_g(1:3) ) ! Uihr, hub radial
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
- else
- DO IdxBlade=1,p%BldNd_BladesOut
- iW = p_AD%FVW%Bld2Wings(iRot, IdxBlade)
- DO IdxNode=1,u%BladeMotion(IdxBlade)%NNodes
- y%WriteOutput( OutIdx ) = dot_product(M_pg(3,1:3,IdxBlade), m_AD%FVW_y%W(iW)%Vind(1:3,IdxNode) ) ! Uihr, hub radial
- OutIdx = OutIdx + 1
- ENDDO
- ENDDO
- endif
-
- ! Normal buoyant force (to chord), tangential buoyant force (to chord), spanwise buoyant force
- CASE ( BldNd_Fbn )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( u%BladeMotion(IdxBlade)%Orientation(1,:,IdxNode), m%BlFB(IdxNode,IdxBlade,:) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_Fbt )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( u%BladeMotion(IdxBlade)%Orientation(2,:,IdxNode), m%BlFB(IdxNode,IdxBlade,:) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_Fbs )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( u%BladeMotion(IdxBlade)%Orientation(3,:,IdxNode), m%BlFB(IdxNode,IdxBlade,:) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- ! Normal buoyant moment (to chord), tangential buoyant moment (to chord), spanwise buoyant moment
- CASE ( BldNd_Mbn )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( u%BladeMotion(IdxBlade)%Orientation(1,:,IdxNode), m%BlMB(IdxNode,IdxBlade,:) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_Mbt )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( u%BladeMotion(IdxBlade)%Orientation(2,:,IdxNode), m%BlMB(IdxNode,IdxBlade,:) )
- OutIdx = OutIdx + 1
- END DO
- END DO
-
- CASE ( BldNd_Mbs )
- DO IdxBlade=1,p%BldNd_BladesOut
- DO IdxNode=1,p%NumBlNds
- y%WriteOutput( OutIdx ) = dot_product( u%BladeMotion(IdxBlade)%Orientation(3,:,IdxNode), m%BlMB(IdxNode,IdxBlade,:) )
- OutIdx = OutIdx + 1
- END DO
- END DO
+ !================================================ BEM ONLY
+
+ ! BEM variables: F: Hub/Tip-loss factor, k/kp: load factors, CT: thrust coefficient in CT-a relationship
+ CASE(BldNd_BEM_F_qs ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BEMT_y%F(iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE(BldNd_BEM_k_qs ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BEMT_y%k(iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE(BldNd_BEM_kp_qs ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BEMT_y%k_p(iNd,iB); iOut = iOut + 1; enddo;enddo
+ CASE(BldNd_BEM_CT_qs ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = 4*m%BEMT_y%F(iNd,iB)*m%BEMT_y%k(iNd,iB)*(1._ReKi-m%BEMT_y%axInduction_qs(iNd,iB))**2; iOut = iOut + 1; enddo;enddo
+
+ !================================================ MHK only
+
+ ! Buoyant force in inertial, polar, local and airfoil systems
+ CASE( BldNd_Fbxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BladeBuoyLoad(iB)%Force (1,iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbyi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BladeBuoyLoad(iB)%Force (2,iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbzi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BladeBuoyLoad(iB)%Force (3,iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbxi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BladeBuoyLoad(iB)%Moment(1,iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbyi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BladeBuoyLoad(iB)%Moment(2,iNd); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbzi ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = m%BladeBuoyLoad(iB)%Moment(3,iNd); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Fbxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), R_pi(1,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbyp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), R_pi(2,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbzp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), R_pi(3,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbxp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), R_pi(1,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbyp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), R_pi(2,:,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbzp ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), R_pi(3,:,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Fbxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), R_li(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbyl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), R_li(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbzl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), R_li(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbxl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), R_li(1,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbyl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), R_li(2,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbzl ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), R_li(3,:,iNd,iB) ); iOut = iOut + 1; enddo;enddo
+
+ CASE( BldNd_Fbxa ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), u%BladeMotion(iB)%Orientation(1,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbya ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), u%BladeMotion(iB)%Orientation(2,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Fbza ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Force (:,iNd), u%BladeMotion(iB)%Orientation(3,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbxa ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), u%BladeMotion(iB)%Orientation(1,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbya ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), u%BladeMotion(iB)%Orientation(2,:,iNd) ); iOut = iOut + 1; enddo;enddo
+ CASE( BldNd_Mbza ); do iB=1,nB; do iNd=1,nNd; y%WriteOutput(iOut) = dot_product( m%BladeBuoyLoad(iB)%Moment(:,iNd), u%BladeMotion(iB)%Orientation(3,:,iNd) ); iOut = iOut + 1; enddo;enddo
+
+ !================================================ DEBUG ONLY
+
+ ! Convenient placeholders for debuging
+ CASE ( BldNd_Debug1 ); do iB=1,nB; do iNd=1,u%BladeMotion(iB)%NNodes; y%WriteOutput(iOut) = 0.0_ReKi; iOut = iOut + 1; enddo;enddo
+ CASE ( BldNd_Debug2 ); do iB=1,nB; do iNd=1,u%BladeMotion(iB)%NNodes; y%WriteOutput(iOut) = 0.0_ReKi; iOut = iOut + 1; enddo;enddo
+ CASE ( BldNd_Debug3 ); do iB=1,nB; do iNd=1,u%BladeMotion(iB)%NNodes; y%WriteOutput(iOut) = 0.0_ReKi; iOut = iOut + 1; enddo;enddo
+
+ CASE DEFAULT
+ ! Should never happen, this is a programmer's error
+ CALL SetErrStat( ErrID_Fatal, "The channel was not implemented, index: "//trim(num2lstr(p%BldNd_OutParam(IdxChan)%Indx)), ErrStat, ErrMsg, RoutineName )
END SELECT
@@ -1373,7 +1403,7 @@ END SUBROUTINE AllBldNdOuts_SetParameters
!! the sign is set to 0 if the channel is invalid.
!! It sets assumes the value p%NumOuts has been set before this routine has been called, and it sets the values of p%OutParam here.
!!
-!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx at 07-Sep-2022 16:16:13.
+!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx.
SUBROUTINE BldNdOuts_SetOutParam(BldNd_OutList, p, p_AD, ErrStat, ErrMsg )
!..................................................................................................................................
@@ -1396,37 +1426,73 @@ SUBROUTINE BldNdOuts_SetOutParam(BldNd_OutList, p, p_AD, ErrStat, ErrMsg )
LOGICAL :: InvalidOutput(1:BldNd_MaxOutPts) ! This array determines if the output channel is valid for this configuration
CHARACTER(*), PARAMETER :: RoutineName = "BldNdOuts_SetOutParam"
-
- CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(68) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically
- "ALPHA ","AXIND ","CD ","CD_STATIC","CHI ","CL ","CLRNC ","CL_STATIC", &
- "CM ","CM_STATIC","CN ","CPMIN ","CT ","CURVE ","CX ","CY ", &
- "DEBUG1 ","DEBUG2 ","DEBUG3 ","DYNP ","FBN ","FBS ","FBT ","FD ", &
- "FL ","FN ","FT ","FX ","FY ","GAM ","GEOMPHI ","M ", &
- "MBN ","MBS ","MBT ","MM ","PHI ","RE ","SGCAV ","SIGCR ", &
- "STVX ","STVY ","STVZ ","THETA ","TNIND ","UA_FLAG ","UA_X1 ","UA_X2 ", &
- "UA_X3 ","UA_X4 ","UA_X5 ","UIN ","UIR ","UIT ","VDISX ","VDISY ", &
- "VDISZ ","VINDX ","VINDY ","VREL ","VUNDX ","VUNDXI ","VUNDY ","VUNDYI ", &
- "VUNDZ ","VUNDZI ","VX ","VY "/)
- INTEGER(IntKi), PARAMETER :: ParamIndxAry(68) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:)
- BldNd_Alpha , BldNd_AxInd , BldNd_Cd , BldNd_Cd_Static , BldNd_Chi , BldNd_Cl , BldNd_Clrnc , BldNd_Cl_Static , &
- BldNd_Cm , BldNd_Cm_Static , BldNd_Cn , BldNd_CpMin , BldNd_Ct , BldNd_Curve , BldNd_Cx , BldNd_Cy , &
- BldNd_Debug1 , BldNd_Debug2 , BldNd_Debug3 , BldNd_DynP , BldNd_Fbn , BldNd_Fbs , BldNd_Fbt , BldNd_Fd , &
- BldNd_Fl , BldNd_Fn , BldNd_Ft , BldNd_Fx , BldNd_Fy , BldNd_Gam , BldNd_GeomPhi , BldNd_M , &
- BldNd_Mbn , BldNd_Mbs , BldNd_Mbt , BldNd_Mm , BldNd_Phi , BldNd_Re , BldNd_SgCav , BldNd_SigCr , &
- BldNd_STVx , BldNd_STVy , BldNd_STVz , BldNd_Theta , BldNd_TnInd , BldNd_UA_Flag , BldNd_UA_x1 , BldNd_UA_x2 , &
- BldNd_UA_x3 , BldNd_UA_x4 , BldNd_UA_x5 , BldNd_Uin , BldNd_Uir , BldNd_Uit , BldNd_VDisx , BldNd_VDisy , &
- BldNd_VDisz , BldNd_Vindx , BldNd_Vindy , BldNd_VRel , BldNd_VUndx , BldNd_Vundxi , BldNd_VUndy , BldNd_Vundyi , &
- BldNd_VUndz , BldNd_Vundzi , BldNd_Vx , BldNd_Vy /)
- CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(68) = (/ & ! This lists the units corresponding to the allowed parameters
- "(deg) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(m) ","(-) ", &
- "(-) ","(-) ","(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ", &
- "(-) ","(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", &
- "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(m^2/s)","(1/0) ","(-) ", &
- "(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(deg) ","(-) ","(-) ","(-) ", &
- "(m/s) ","(m/s) ","(m/s) ","(deg) ","(-) ","(-) ","(rad) ","(rad) ", &
+
+ CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(166) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically
+ "ALPHA ","AXIND ","AXIND_QS ","BEM_CT_QS","BEM_F_QS ","BEM_KP_QS","BEM_K_QS ","CD ", &
+ "CD_QS ","CHI ","CL ","CLRNC ","CL_QS ","CM ","CMA ","CM_QS ", &
+ "CN ","CPMIN ","CT ","CURVE ","CX ","CXA ","CY ","DEBUG1 ", &
+ "DEBUG2 ","DEBUG3 ","DYNP ","FBN ","FBS ","FBT ","FBXA ","FBXI ", &
+ "FBXL ","FBXP ","FBYA ","FBYI ","FBYL ","FBYP ","FBZA ","FBZI ", &
+ "FBZL ","FBZP ","FD ","FL ","FN ","FT ","FX ","FXA ", &
+ "FXI ","FXL ","FXP ","FY ","FYI ","FYL ","FYP ","FZI ", &
+ "FZL ","FZP ","GAM ","GEOMPHI ","M ","MBN ","MBS ","MBT ", &
+ "MBXA ","MBXI ","MBXL ","MBXP ","MBYA ","MBYI ","MBYL ","MBYP ", &
+ "MBZA ","MBZI ","MBZL ","MBZP ","MM ","MXI ","MXL ","MXP ", &
+ "MYI ","MYL ","MYP ","MZA ","MZI ","MZL ","MZP ","PHI ", &
+ "RE ","SGCAV ","SIGCR ","STVX ","STVXA ","STVXI ","STVXL ","STVXP ", &
+ "STVY ","STVYA ","STVYI ","STVYL ","STVYP ","STVZ ","STVZA ","STVZI ", &
+ "STVZL ","STVZP ","THETA ","TNIND ","TNIND_QS ","TOE ","UA_FLAG ","UA_X1 ", &
+ "UA_X2 ","UA_X3 ","UA_X4 ","UA_X5 ","UIN ","UIR ","UIT ","VDISX ", &
+ "VDISXA ","VDISXI ","VDISXL ","VDISXP ","VDISY ","VDISYA ","VDISYI ","VDISYL ", &
+ "VDISYP ","VDISZ ","VDISZA ","VDISZI ","VDISZL ","VDISZP ","VINDX ","VINDXA ", &
+ "VINDXI ","VINDXL ","VINDXP ","VINDY ","VINDYA ","VINDYI ","VINDYL ","VINDYP ", &
+ "VINDZA ","VINDZI ","VINDZL ","VINDZP ","VREL ","VUNDX ","VUNDXA ","VUNDXI ", &
+ "VUNDXL ","VUNDXP ","VUNDY ","VUNDYA ","VUNDYI ","VUNDYL ","VUNDYP ","VUNDZ ", &
+ "VUNDZA ","VUNDZI ","VUNDZL ","VUNDZP ","VX ","VY "/)
+ INTEGER(IntKi), PARAMETER :: ParamIndxAry(166) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:)
+ BldNd_Alpha , BldNd_AxInd , BldNd_AxInd_qs , BldNd_BEM_CT_qs , BldNd_BEM_F_qs , BldNd_BEM_kp_qs , BldNd_BEM_k_qs , BldNd_Cd , &
+ BldNd_Cd_qs , BldNd_Chi , BldNd_Cl , BldNd_Clrnc , BldNd_Cl_qs , BldNd_Cm , BldNd_Cm , BldNd_Cm_qs , &
+ BldNd_Cn , BldNd_CpMin , BldNd_Ct , BldNd_Curve , BldNd_Cx , BldNd_Cn , BldNd_Cy , BldNd_Debug1 , &
+ BldNd_Debug2 , BldNd_Debug3 , BldNd_DynP , BldNd_Fbxa , BldNd_Fbza , BldNd_Fbya , BldNd_Fbxa , BldNd_Fbxi , &
+ BldNd_Fbxl , BldNd_Fbxp , BldNd_Fbya , BldNd_Fbyi , BldNd_Fbyl , BldNd_Fbyp , BldNd_Fbza , BldNd_Fbzi , &
+ BldNd_Fbzl , BldNd_Fbzp , BldNd_Fd , BldNd_Fl , BldNd_Fn , BldNd_Ft , BldNd_Fx , BldNd_Fn , &
+ BldNd_Fxi , BldNd_Fxl , BldNd_Fxp , BldNd_Fy , BldNd_Fyi , BldNd_Fyl , BldNd_Fyp , BldNd_Fzi , &
+ BldNd_Fzl , BldNd_Fzp , BldNd_Gam , BldNd_GeomPhi , BldNd_M , BldNd_Mbxa , BldNd_Mbza , BldNd_Mbya , &
+ BldNd_Mbxa , BldNd_Mbxi , BldNd_Mbxl , BldNd_Mbxp , BldNd_Mbya , BldNd_Mbyi , BldNd_Mbyl , BldNd_Mbyp , &
+ BldNd_Mbza , BldNd_Mbzi , BldNd_Mbzl , BldNd_Mbzp , BldNd_Mm , BldNd_Mxi , BldNd_Mxl , BldNd_Mxp , &
+ BldNd_Myi , BldNd_Myl , BldNd_Myp , BldNd_Mm , BldNd_Mzi , BldNd_Mzl , BldNd_Mzp , BldNd_Phi , &
+ BldNd_Re , BldNd_SgCav , BldNd_SigCr , BldNd_STVx , BldNd_STVxa , BldNd_STVxi , BldNd_STVxl , BldNd_STVxp , &
+ BldNd_STVy , BldNd_STVya , BldNd_STVyi , BldNd_STVyl , BldNd_STVyp , BldNd_STVz , BldNd_STVza , BldNd_STVzi , &
+ BldNd_STVzl , BldNd_STVzp , BldNd_Theta , BldNd_TnInd , BldNd_TnInd_qs , BldNd_Toe , BldNd_UA_Flag , BldNd_UA_x1 , &
+ BldNd_UA_x2 , BldNd_UA_x3 , BldNd_UA_x4 , BldNd_UA_x5 , BldNd_Vindxp , BldNd_Vindzp , BldNd_Vindyp , BldNd_VDisx , &
+ BldNd_VDisxa , BldNd_VDisxi , BldNd_VDisxl , BldNd_VDisxp , BldNd_VDisy , BldNd_VDisya , BldNd_VDisyi , BldNd_VDisyl , &
+ BldNd_VDisyp , BldNd_VDisz , BldNd_VDisza , BldNd_VDiszi , BldNd_VDiszl , BldNd_VDiszp , BldNd_Vindx , BldNd_Vindxa , &
+ BldNd_Vindxi , BldNd_Vindxl , BldNd_Vindxp , BldNd_Vindy , BldNd_Vindya , BldNd_Vindyi , BldNd_Vindyl , BldNd_Vindyp , &
+ BldNd_Vindza , BldNd_Vindzi , BldNd_Vindzl , BldNd_Vindzp , BldNd_VRel , BldNd_VUndx , BldNd_VUndxa , BldNd_VUndxi , &
+ BldNd_VUndxl , BldNd_VUndxp , BldNd_VUndy , BldNd_VUndya , BldNd_VUndyi , BldNd_VUndyl , BldNd_VUndyp , BldNd_VUndz , &
+ BldNd_VUndza , BldNd_VUndzi , BldNd_VUndzl , BldNd_VUndzp , BldNd_Vx , BldNd_Vy /)
+ CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(166) = (/ character(ChanLen) :: & ! This lists the units corresponding to the allowed parameters
+ "(deg) ","(-) ","(-) ","(-) ","(-) ","(-) ","(-) ","(-) ", &
+ "(-) ","(deg) ","(-) ","(m) ","(-) ","(-) ","(-) ","(-) ", &
+ "(-) ","(-) ","(-) ","(deg) ","(-) ","(-) ","(-) ","(-) ", &
+ "(-) ","(-) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", &
+ "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", &
+ "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", &
+ "(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", &
+ "(N/m) ","(N/m) ","(m^2/s)","(1/0) ","(-) ","(N-m/m)","(N-m/m)","(N-m/m)", &
+ "(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)", &
+ "(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)", &
+ "(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(N-m/m)","(deg) ", &
"(-) ","(-) ","(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
"(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
- "(m/s) ","(m/s) ","(m/s) ","(m/s) "/)
+ "(m/s) ","(m/s) ","(deg) ","(-) ","(-) ","(deg) ","(-) ","(rad) ", &
+ "(rad) ","(-) ","(-) ","(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) "/)
! Initialize values
@@ -1438,26 +1504,54 @@ SUBROUTINE BldNdOuts_SetOutParam(BldNd_OutList, p, p_AD, ErrStat, ErrMsg )
! ..... Developer must add checking for invalid inputs here: .....
if (.not. p%Buoyancy) then
- InvalidOutput( BldNd_Fbn ) = .true.
- InvalidOutput( BldNd_Fbt ) = .true.
- InvalidOutput( BldNd_Fbs ) = .true.
- InvalidOutput( BldNd_Mbn ) = .true.
- InvalidOutput( BldNd_Mbt ) = .true.
- InvalidOutput( BldNd_Mbs ) = .true.
+ InvalidOutput( BldNd_Fbxi ) = .true.
+ InvalidOutput( BldNd_Fbyi ) = .true.
+ InvalidOutput( BldNd_Fbzi ) = .true.
+ InvalidOutput( BldNd_Mbxi ) = .true.
+ InvalidOutput( BldNd_Mbyi ) = .true.
+ InvalidOutput( BldNd_Mbzi ) = .true.
+ InvalidOutput( BldNd_Fbxp ) = .true.
+ InvalidOutput( BldNd_Fbyp ) = .true.
+ InvalidOutput( BldNd_Fbzp ) = .true.
+ InvalidOutput( BldNd_Mbxp ) = .true.
+ InvalidOutput( BldNd_Mbyp ) = .true.
+ InvalidOutput( BldNd_Mbzp ) = .true.
+ InvalidOutput( BldNd_Fbxl ) = .true.
+ InvalidOutput( BldNd_Fbyl ) = .true.
+ InvalidOutput( BldNd_Fbzl ) = .true.
+ InvalidOutput( BldNd_Mbxl ) = .true.
+ InvalidOutput( BldNd_Mbyl ) = .true.
+ InvalidOutput( BldNd_Mbzl ) = .true.
+ InvalidOutput( BldNd_Fbxa ) = .true.
+ InvalidOutput( BldNd_Fbya ) = .true.
+ InvalidOutput( BldNd_Fbza ) = .true.
+ InvalidOutput( BldNd_Mbxa ) = .true.
+ InvalidOutput( BldNd_Mbya ) = .true.
+ InvalidOutput( BldNd_Mbza ) = .true.
end if
! The following are valid only for BEMT/DBEMT
if (p_AD%WakeMod /= WakeMod_FVW) then
- InvalidOutput( BldNd_Cl_Static ) = .true.
- InvalidOutput( BldNd_Cd_Static ) = .true.
- InvalidOutput( BldNd_Cm_Static ) = .true.
+ InvalidOutput( BldNd_Cl_qs ) = .true.
+ InvalidOutput( BldNd_Cd_qs ) = .true.
+ InvalidOutput( BldNd_Cm_qs ) = .true.
else
- ! The following are invalid for free vortex wake
+ ! The following are invalid for free vortex wake
+ InvalidOutput( BldNd_Toe ) = .true.
InvalidOutput( BldNd_Chi ) = .true.
InvalidOutput( BldNd_Curve ) = .true.
- InvalidOutput( BldNd_GeomPhi ) = .true. ! applies only to BEM
+ InvalidOutput( BldNd_GeomPhi ) = .true.
+ endif
+
+ ! The following are valid only for BEMT/DBEMT
+ if (p_AD%WakeMod /= WakeMod_BEMT) then
+ InvalidOutput( BldNd_BEM_F_qs ) = .true.
+ InvalidOutput( BldNd_BEM_k_qs ) = .true.
+ InvalidOutput( BldNd_BEM_kp_qs ) = .true.
+ InvalidOutput( BldNd_BEM_CT_qs ) = .true.
endif
+
! it's going to be very difficult to get the FVW states without rewriting a bunch of code
if (.not. p_AD%UA_Flag .or. p_AD%WakeMod == WakeMod_FVW) then ! also invalid if AFAeroMod is not 4,5,6
InvalidOutput( BldNd_UA_x1 ) = .true.
diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90
index 2af1a7f720..8227a8252a 100644
--- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90
+++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90
@@ -391,7 +391,9 @@ subroutine Dvr_CleanUp(dvr, ADI, FED, initialized, errStat, errMsg)
call Dvr_EndCase(dvr, ADI, initialized, errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, RoutineName)
! End modules
- call ADI_End( ADI%u(:), ADI%p, ADI%x(1), ADI%xd(1), ADI%z(1), ADI%OtherState(1), ADI%y, ADI%m, errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, RoutineName);
+ if (allocated(ADI%x)) then
+ call ADI_End( ADI%u(:), ADI%p, ADI%x(1), ADI%xd(1), ADI%z(1), ADI%OtherState(1), ADI%y, ADI%m, errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, RoutineName);
+ endif
call AD_Dvr_DestroyDvr_SimData (dvr , errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, RoutineName)
diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90
index b8ab0babd8..24e56b0ab2 100644
--- a/modules/aerodyn/src/AeroDyn_IO.f90
+++ b/modules/aerodyn/src/AeroDyn_IO.f90
@@ -288,28 +288,28 @@ subroutine Calc_WriteOutput_AD()
force = force + m%HubLoad%force( :,1)
moment = moment + m%HubLoad%moment(:,1)
- if (k<=size(BAeroFxg)) then
+ if (k<=size(BAeroFxi)) then
! Power contribution of blade wrt hub
tmp = matmul( u%HubMotion%Orientation(:,:,1), m%HubLoad%moment(:,1) )
m%AllOuts( BAeroPwr(k) ) = omega * tmp(1)
! In global, wrt hub!
- m%AllOuts( BAeroFxg(k) ) = m%HubLoad%force(1,1)
- m%AllOuts( BAeroFyg(k) ) = m%HubLoad%force(2,1)
- m%AllOuts( BAeroFzg(k) ) = m%HubLoad%force(3,1)
- m%AllOuts( BAeroMxg(k) ) = m%HubLoad%moment(1,1)
- m%AllOuts( BAeroMyg(k) ) = m%HubLoad%moment(2,1)
- m%AllOuts( BAeroMzg(k) ) = m%HubLoad%moment(3,1)
+ m%AllOuts( BAeroFxi(k) ) = m%HubLoad%force(1,1)
+ m%AllOuts( BAeroFyi(k) ) = m%HubLoad%force(2,1)
+ m%AllOuts( BAeroFzi(k) ) = m%HubLoad%force(3,1)
+ m%AllOuts( BAeroMxi(k) ) = m%HubLoad%moment(1,1)
+ m%AllOuts( BAeroMyi(k) ) = m%HubLoad%moment(2,1)
+ m%AllOuts( BAeroMzi(k) ) = m%HubLoad%moment(3,1)
end if
end do
! In global
- m%AllOuts( RtAeroFxg ) = force(1)
- m%AllOuts( RtAeroFyg ) = force(2)
- m%AllOuts( RtAeroFzg ) = force(3)
- m%AllOuts( RtAeroMxg ) = moment(1)
- m%AllOuts( RtAeroMyg ) = moment(2)
- m%AllOuts( RtAeroMzg ) = moment(3)
+ m%AllOuts( RtAeroFxi ) = force(1)
+ m%AllOuts( RtAeroFyi ) = force(2)
+ m%AllOuts( RtAeroFzi ) = force(3)
+ m%AllOuts( RtAeroMxi ) = moment(1)
+ m%AllOuts( RtAeroMyi ) = moment(2)
+ m%AllOuts( RtAeroMzi ) = moment(3)
tmp = matmul( u%HubMotion%Orientation(:,:,1), force )
m%AllOuts( RtAeroFxh ) = tmp(1)
m%AllOuts( RtAeroFyh ) = tmp(2)
@@ -378,17 +378,28 @@ end subroutine Calc_WriteOutput_AD
subroutine Calc_WriteOutput_BEMT()
REAL(R8Ki) :: orient(3,3)
REAL(R8Ki) :: theta(3)
+ REAL(ReKi) :: Vind_s(3) ! Induced velocity in "w" or "p" system
REAL(ReKi) :: denom !, rmax
REAL(ReKi) :: ct, st ! cosine, sine of theta
REAL(ReKi) :: cp, sp ! cosine, sine of phi
+ ! Induced velocity in Global
+ do k=1,min(p%numBlades,3)
+ do j=1,u%BladeMotion(k)%NNodes
+ !if(p%BEM_Mod==BEMMod_2D) then
+ ! NOTE: if BEMMod_2D: x & y are in "w" system (WithoutSweepPitchTwist)
+ ! if BEMMod_3D: x & y are in "l" system (local-polar system)
+ Vind_s = (/ -m%BEMT_u(indx)%Vx(j,k)*m%BEMT_y%axInduction(j,k), m%BEMT_u(indx)%Vy(j,k)*m%BEMT_y%tanInduction(j,k), 0.0_ReKi /)
+ m%Vind_i(:,j,k) = matmul(Vind_s, m%orientationAnnulus(:,:,j,k)) ! TODO rename orientationAnnulus
+ enddo
+ enddo
! blade outputs
do k=1,min(p%numBlades,AD_MaxBl_Out) ! limit this
- m%AllOuts( BAzimuth(k) ) = MODULO( m%BEMT_u(indx)%psi(k)*R2D, 360.0_ReKi )
+ m%AllOuts( BAzimuth(k) ) = MODULO( m%BEMT_u(indx)%psi_s(k)*R2D, 360.0_ReKi )
! m%AllOuts( BPitch( k) ) = calculated in SetInputsForBEMT
do beta=1,p%NBlOuts
@@ -462,6 +473,17 @@ end subroutine Calc_WriteOutput_BEMT
subroutine Calc_WriteOutput_FVW
integer :: iW
+ ! Induced velocity in global
+ ! FVW already return this, we do a simple copy from Wings to Blades
+ do k=1,min(p%numBlades,3)
+ iW = p_AD%FVW%Bld2Wings(iRot, k)
+ do j=1,u%BladeMotion(k)%NNodes
+ m%Vind_i(:,j,k) = m_AD%FVW_y%W(iW)%Vind(1:3,j)
+ enddo
+ enddo
+
+ ! TODO TODO TODO ALL THIS SHOULD BE COMPUTED IN THE SAME MEMORY FORMAT AS AERODYN
+
! blade outputs
do k=1,min(p%numBlades,3)
iW=p_AD%FVW%Bld2Wings(iRot, k)
@@ -993,6 +1015,10 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade
call ReadOutputListFromFileInfo( FileInfo_In, CurLine, InputFileData%BldNd_OutList, InputFileData%BldNd_NumOuts, ErrStat2, ErrMsg2, UnEc )
if (FailedNodal()) return;
+!FIXME: improve logic on the node outputs
+ ! Prevent segfault when no blades specified. All logic tests on BldNd_NumOuts at present.
+ if (InputFileData%BldNd_BladesOut <= 0) InputFileData%BldNd_NumOuts = 0
+
RETURN
CONTAINS
!-------------------------------------------------------------------------------------------------
@@ -2114,49 +2140,37 @@ subroutine calcCantAngle(f, xi,stencilSize,n,cantAngle)
implicit none
integer(IntKi), intent(in) :: stencilSize, n
integer(IntKi) :: i, j
- integer(IntKi) :: sortInd(n)
integer(IntKi) :: info
real(ReKi), intent(in) :: f(n), xi(n)
real(ReKi) :: cx(stencilSize), cf(stencilSize), xiIn(stencilSize)
- real(ReKi) :: fIn(stencilSize), cPrime(n), fPrime(n), xiAbs(n)
+ real(ReKi) :: fIn(stencilSize), cPrime(n), fPrime(n)
real(ReKi), intent(inout) :: cantAngle(n)
do i = 1,size(xi)
- xiAbs = abs(xi-xi(i))
- call hpsort_eps_epw (n, xiAbs, sortInd, 1e-6)
-
if (i.eq.1) then
fIn = f(1:stencilSize)
xiIn = xi(1:stencilSize)
- call differ_stencil ( xi(i), 1, 2, xiIn, cx, info )
- if (info /= 0) return ! use default cantAngle in this case
- call differ_stencil ( xi(i), 1, 2, fIn, cf, info )
- if (info /= 0) return ! use default cantAngle in this case
elseif (i.eq.size(xi)) then
fIn = f(size(xi)-stencilSize +1:size(xi))
xiIn = xi(size(xi)-stencilSize+1:size(xi))
- call differ_stencil ( xi(i), 1, 2, xiIn, cx, info )
- if (info /= 0) return ! use default cantAngle in this case
- call differ_stencil ( xi(i), 1, 2, fIn, cf, info )
- if (info /= 0) return ! use default cantAngle in this case
else
fIn = f(i-1:i+1)
xiIn = xi(i-1:i+1)
- call differ_stencil ( xi(i), 1, 2, xiIn, cx, info )
- if (info /= 0) return ! use default cantAngle in this case
- call differ_stencil ( xi(i), 1, 2, fIn, cf, info )
- if (info /= 0) return ! use default cantAngle in this case
endif
-
- cPrime(i) = 0.0
- fPrime(i) = 0.0
-
- do j = 1,size(cx)
- cPrime(i) = cPrime(i) + cx(j)*xiIn(j)
- fPrime(i) = fPrime(i) + cx(j)*fIn(j)
- end do
- cantAngle(i) = atan2(fPrime(i),cPrime(i))*180_ReKi/pi
+ call differ_stencil ( xi(i), 1, 2, xiIn, cx, info )
+ !call differ_stencil ( xi(i), 1, 2, fIn, cf, info )
+ if (info /= 0) then
+ print*,'Cant Calc failed at i=',i
+ else
+ cPrime(i) = 0.0
+ fPrime(i) = 0.0
+ do j = 1,size(cx)
+ cPrime(i) = cPrime(i) + cx(j)*xiIn(j)
+ fPrime(i) = fPrime(i) + cx(j)*fIn(j)
+ end do
+ cantAngle(i) = atan2(fPrime(i),cPrime(i))*180_ReKi/pi
+ endif
end do
end subroutine calcCantAngle
@@ -2370,147 +2384,5 @@ subroutine r8vm_sl ( n, a, b, x, job, info )
return
end subroutine r8vm_sl
-!
- ! Copyright (C) 2010-2016 Samuel Ponce', Roxana Margine, Carla Verdi, Feliciano Giustino
- ! Copyright (C) 2007-2009 Jesse Noffsinger, Brad Malone, Feliciano Giustino
- !
- ! This file is distributed under the terms of the GNU General Public
- ! License. See the file `LICENSE' in the root directory of the
- ! present distribution, or http://www.gnu.org/copyleft.gpl.txt .
- !
- ! Adapted from flib/hpsort_eps
- !---------------------------------------------------------------------
- subroutine hpsort_eps_epw (n, ra, ind, eps)
- !---------------------------------------------------------------------
- ! sort an array ra(1:n) into ascending order using heapsort algorithm,
- ! and considering two elements being equal if their values differ
- ! for less than "eps".
- ! n is input, ra is replaced on output by its sorted rearrangement.
- ! create an index table (ind) by making an exchange in the index array
- ! whenever an exchange is made on the sorted data array (ra).
- ! in case of equal values in the data array (ra) the values in the
- ! index array (ind) are used to order the entries.
- ! if on input ind(1) = 0 then indices are initialized in the routine,
- ! if on input ind(1) != 0 then indices are assumed to have been
- ! initialized before entering the routine and these
- ! indices are carried around during the sorting process
- !
- ! no work space needed !
- ! free us from machine-dependent sorting-routines !
- !
- ! adapted from Numerical Recipes pg. 329 (new edition)
- !
- !use kinds, ONLY : DP
- implicit none
- !-input/output variables
- integer(IntKi), intent(in) :: n
- real(ReKi), intent(in) :: eps
- integer(IntKi) :: ind (n)
- real(ReKi) :: ra (n)
- !-local variables
- integer(IntKi) :: i, ir, j, l, iind
- real(ReKi) :: rra
-!
- ! initialize index array
- IF (ind (1) .eq.0) then
- DO i = 1, n
- ind (i) = i
- ENDDO
- ENDIF
- ! nothing to order
- IF (n.lt.2) return
- ! initialize indices for hiring and retirement-promotion phase
- l = n / 2 + 1
-
- ir = n
-
- sorting: do
-
- ! still in hiring phase
- IF ( l .gt. 1 ) then
- l = l - 1
- rra = ra (l)
- iind = ind (l)
- ! in retirement-promotion phase.
- ELSE
- ! clear a space at the end of the array
- rra = ra (ir)
- !
- iind = ind (ir)
- ! retire the top of the heap into it
- ra (ir) = ra (1)
- !
- ind (ir) = ind (1)
- ! decrease the size of the corporation
- ir = ir - 1
- ! done with the last promotion
- IF ( ir .eq. 1 ) then
- ! the least competent worker at all !
- ra (1) = rra
- !
- ind (1) = iind
- exit sorting
- ENDIF
- ENDIF
- ! wheter in hiring or promotion phase, we
- i = l
- ! set up to place rra in its proper level
- j = l + l
- !
- DO while ( j .le. ir )
- IF ( j .lt. ir ) then
- ! compare to better underling
- IF ( hslt( ra (j), ra (j + 1) ) ) then
- j = j + 1
- !else if ( .not. hslt( ra (j+1), ra (j) ) ) then
- ! this means ra(j) == ra(j+1) within tolerance
- ! if (ind (j) .lt.ind (j + 1) ) j = j + 1
- ENDIF
- ENDIF
- ! demote rra
- IF ( hslt( rra, ra (j) ) ) then
- ra (i) = ra (j)
- ind (i) = ind (j)
- i = j
- j = j + j
- !else if ( .not. hslt ( ra(j) , rra ) ) then
- !this means rra == ra(j) within tolerance
- ! demote rra
- ! if (iind.lt.ind (j) ) then
- ! ra (i) = ra (j)
- ! ind (i) = ind (j)
- ! i = j
- ! j = j + j
- ! else
- ! set j to terminate do-while loop
- ! j = ir + 1
- ! endif
- ! this is the right place for rra
- ELSE
- ! set j to terminate do-while loop
- j = ir + 1
- ENDIF
- ENDDO
- ra (i) = rra
- ind (i) = iind
-
- END DO sorting
-contains
-
- ! internal function
- ! compare two real number and return the result
-
- logical function hslt( a, b )
- REAL(ReKi) :: a, b
- IF( abs(a-b) < eps ) then
- hslt = .false.
- ELSE
- hslt = ( a < b )
- end if
- end function hslt
-
- !
-end subroutine hpsort_eps_epw
-
!----------------------------------------------------------------------------------------------------------------------------------
END MODULE AeroDyn_IO
diff --git a/modules/aerodyn/src/AeroDyn_IO_Params.f90 b/modules/aerodyn/src/AeroDyn_IO_Params.f90
index 34ea815754..3568cd8b32 100644
--- a/modules/aerodyn/src/AeroDyn_IO_Params.f90
+++ b/modules/aerodyn/src/AeroDyn_IO_Params.f90
@@ -228,30 +228,30 @@ module AeroDyn_IO_Params
INTEGER(IntKi), PARAMETER :: B4AeroMy = 194
INTEGER(IntKi), PARAMETER :: B4AeroMz = 195
INTEGER(IntKi), PARAMETER :: B4AeroPwr = 196
- INTEGER(IntKi), PARAMETER :: B1AeroFxg = 197
- INTEGER(IntKi), PARAMETER :: B1AeroFyg = 198
- INTEGER(IntKi), PARAMETER :: B1AeroFzg = 199
- INTEGER(IntKi), PARAMETER :: B1AeroMxg = 200
- INTEGER(IntKi), PARAMETER :: B1AeroMyg = 201
- INTEGER(IntKi), PARAMETER :: B1AeroMzg = 202
- INTEGER(IntKi), PARAMETER :: B2AeroFxg = 203
- INTEGER(IntKi), PARAMETER :: B2AeroFyg = 204
- INTEGER(IntKi), PARAMETER :: B2AeroFzg = 205
- INTEGER(IntKi), PARAMETER :: B2AeroMxg = 206
- INTEGER(IntKi), PARAMETER :: B2AeroMyg = 207
- INTEGER(IntKi), PARAMETER :: B2AeroMzg = 208
- INTEGER(IntKi), PARAMETER :: B3AeroFxg = 209
- INTEGER(IntKi), PARAMETER :: B3AeroFyg = 210
- INTEGER(IntKi), PARAMETER :: B3AeroFzg = 211
- INTEGER(IntKi), PARAMETER :: B3AeroMxg = 212
- INTEGER(IntKi), PARAMETER :: B3AeroMyg = 213
- INTEGER(IntKi), PARAMETER :: B3AeroMzg = 214
- INTEGER(IntKi), PARAMETER :: B4AeroFxg = 215
- INTEGER(IntKi), PARAMETER :: B4AeroFyg = 216
- INTEGER(IntKi), PARAMETER :: B4AeroFzg = 217
- INTEGER(IntKi), PARAMETER :: B4AeroMxg = 218
- INTEGER(IntKi), PARAMETER :: B4AeroMyg = 219
- INTEGER(IntKi), PARAMETER :: B4AeroMzg = 220
+ INTEGER(IntKi), PARAMETER :: B1AeroFxi = 197
+ INTEGER(IntKi), PARAMETER :: B1AeroFyi = 198
+ INTEGER(IntKi), PARAMETER :: B1AeroFzi = 199
+ INTEGER(IntKi), PARAMETER :: B1AeroMxi = 200
+ INTEGER(IntKi), PARAMETER :: B1AeroMyi = 201
+ INTEGER(IntKi), PARAMETER :: B1AeroMzi = 202
+ INTEGER(IntKi), PARAMETER :: B2AeroFxi = 203
+ INTEGER(IntKi), PARAMETER :: B2AeroFyi = 204
+ INTEGER(IntKi), PARAMETER :: B2AeroFzi = 205
+ INTEGER(IntKi), PARAMETER :: B2AeroMxi = 206
+ INTEGER(IntKi), PARAMETER :: B2AeroMyi = 207
+ INTEGER(IntKi), PARAMETER :: B2AeroMzi = 208
+ INTEGER(IntKi), PARAMETER :: B3AeroFxi = 209
+ INTEGER(IntKi), PARAMETER :: B3AeroFyi = 210
+ INTEGER(IntKi), PARAMETER :: B3AeroFzi = 211
+ INTEGER(IntKi), PARAMETER :: B3AeroMxi = 212
+ INTEGER(IntKi), PARAMETER :: B3AeroMyi = 213
+ INTEGER(IntKi), PARAMETER :: B3AeroMzi = 214
+ INTEGER(IntKi), PARAMETER :: B4AeroFxi = 215
+ INTEGER(IntKi), PARAMETER :: B4AeroFyi = 216
+ INTEGER(IntKi), PARAMETER :: B4AeroFzi = 217
+ INTEGER(IntKi), PARAMETER :: B4AeroMxi = 218
+ INTEGER(IntKi), PARAMETER :: B4AeroMyi = 219
+ INTEGER(IntKi), PARAMETER :: B4AeroMzi = 220
! Blade Nodal outputs:
@@ -1520,12 +1520,12 @@ module AeroDyn_IO_Params
INTEGER(IntKi), PARAMETER :: RtAeroCq = 1478
INTEGER(IntKi), PARAMETER :: RtAeroCt = 1479
INTEGER(IntKi), PARAMETER :: DBEMTau1 = 1480
- INTEGER(IntKi), PARAMETER :: RtAeroFxg = 1481
- INTEGER(IntKi), PARAMETER :: RtAeroFyg = 1482
- INTEGER(IntKi), PARAMETER :: RtAeroFzg = 1483
- INTEGER(IntKi), PARAMETER :: RtAeroMxg = 1484
- INTEGER(IntKi), PARAMETER :: RtAeroMyg = 1485
- INTEGER(IntKi), PARAMETER :: RtAeroMzg = 1486
+ INTEGER(IntKi), PARAMETER :: RtAeroFxi = 1481
+ INTEGER(IntKi), PARAMETER :: RtAeroFyi = 1482
+ INTEGER(IntKi), PARAMETER :: RtAeroFzi = 1483
+ INTEGER(IntKi), PARAMETER :: RtAeroMxi = 1484
+ INTEGER(IntKi), PARAMETER :: RtAeroMyi = 1485
+ INTEGER(IntKi), PARAMETER :: RtAeroMzi = 1486
! Hub:
@@ -1626,12 +1626,12 @@ module AeroDyn_IO_Params
INTEGER, PARAMETER :: BAeroMy(4) = (/B1AeroMy, B2AeroMy, B3AeroMy, B4AeroMy/) ! total blade aero/hydro load (moment in y-direction)
INTEGER, PARAMETER :: BAeroMz(4) = (/B1AeroMz, B2AeroMz, B3AeroMz, B4AeroMz/) ! total blade aero/hydro load (moment in z-direction)
INTEGER, PARAMETER :: BAeroPwr(4) = (/B1AeroPwr, B2AeroPwr, B3AeroPwr, B4AeroPwr/) ! total blade aero/hydro power
- INTEGER, PARAMETER :: BAeroFxg(4) = (/B1AeroFxg, B2AeroFxg, B3AeroFxg, B4AeroFxg/) ! total blade aero/hydro load (force in x-direction) in global
- INTEGER, PARAMETER :: BAeroFyg(4) = (/B1AeroFyg, B2AeroFyg, B3AeroFyg, B4AeroFyg/) ! total blade aero/hydro load (force in y-direction) in global
- INTEGER, PARAMETER :: BAeroFzg(4) = (/B1AeroFzg, B2AeroFzg, B3AeroFzg, B4AeroFzg/) ! total blade aero/hydro load (force in z-direction) in global
- INTEGER, PARAMETER :: BAeroMxg(4) = (/B1AeroMxg, B2AeroMxg, B3AeroMxg, B4AeroMxg/) ! total blade aero/hydro load (moment in x-direction) in global
- INTEGER, PARAMETER :: BAeroMyg(4) = (/B1AeroMyg, B2AeroMyg, B3AeroMyg, B4AeroMyg/) ! total blade aero/hydro load (moment in y-direction) in global
- INTEGER, PARAMETER :: BAeroMzg(4) = (/B1AeroMzg, B2AeroMzg, B3AeroMzg, B4AeroMzg/) ! total blade aero/hydro load (moment in z-direction) in global
+ INTEGER, PARAMETER :: BAeroFxi(4) = (/B1AeroFxi, B2AeroFxi, B3AeroFxi, B4AeroFxi/) ! total blade aero/hydro load (force in x-direction) in global
+ INTEGER, PARAMETER :: BAeroFyi(4) = (/B1AeroFyi, B2AeroFyi, B3AeroFyi, B4AeroFyi/) ! total blade aero/hydro load (force in y-direction) in global
+ INTEGER, PARAMETER :: BAeroFzi(4) = (/B1AeroFzi, B2AeroFzi, B3AeroFzi, B4AeroFzi/) ! total blade aero/hydro load (force in z-direction) in global
+ INTEGER, PARAMETER :: BAeroMxi(4) = (/B1AeroMxi, B2AeroMxi, B3AeroMxi, B4AeroMxi/) ! total blade aero/hydro load (moment in x-direction) in global
+ INTEGER, PARAMETER :: BAeroMyi(4) = (/B1AeroMyi, B2AeroMyi, B3AeroMyi, B4AeroMyi/) ! total blade aero/hydro load (moment in y-direction) in global
+ INTEGER, PARAMETER :: BAeroMzi(4) = (/B1AeroMzi, B2AeroMzi, B3AeroMzi, B4AeroMzi/) ! total blade aero/hydro load (moment in z-direction) in global
INTEGER, PARAMETER :: BNVUndx(9, 3) = RESHAPE( (/ & ! undisturbed wind velocity (x component)
B1N1VUndx,B1N2VUndx,B1N3VUndx,B1N4VUndx,B1N5VUndx,B1N6VUndx,B1N7VUndx,B1N8VUndx,B1N9VUndx, &
@@ -1874,11 +1874,11 @@ module AeroDyn_IO_Params
- CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(1588) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically
- "B1AEROFX ","B1AEROFXG","B1AEROFY ","B1AEROFYG","B1AEROFZ ","B1AEROFZG","B1AEROMX ","B1AEROMXG", &
- "B1AEROMY ","B1AEROMYG","B1AEROMZ ","B1AEROMZG","B1AEROPWR","B1AZIMUTH","B1FLDFX ","B1FLDFXG ", &
- "B1FLDFY ","B1FLDFYG ","B1FLDFZ ","B1FLDFZG ","B1FLDMX ","B1FLDMXG ","B1FLDMY ","B1FLDMYG ", &
- "B1FLDMZ ","B1FLDMZG ","B1FLDPWR ","B1N1ALPHA","B1N1AXIND","B1N1CD ","B1N1CL ","B1N1CLRNC", &
+ CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(1594) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically
+ "B1AEROFX ","B1AEROFXI","B1AEROFY ","B1AEROFYI","B1AEROFZ ","B1AEROFZI","B1AEROMX ","B1AEROMXI", &
+ "B1AEROMY ","B1AEROMYI","B1AEROMZ ","B1AEROMZI","B1AEROPWR","B1AZIMUTH","B1FLDFX ","B1FLDFXI ", &
+ "B1FLDFY ","B1FLDFYI ","B1FLDFZ ","B1FLDFZI ","B1FLDMX ","B1FLDMXI ","B1FLDMY ","B1FLDMYI ", &
+ "B1FLDMZ ","B1FLDMZI ","B1FLDPWR ","B1N1ALPHA","B1N1AXIND","B1N1CD ","B1N1CL ","B1N1CLRNC", &
"B1N1CM ","B1N1CN ","B1N1CPMIN","B1N1CT ","B1N1CURVE","B1N1CX ","B1N1CY ","B1N1DYNP ", &
"B1N1FBN ","B1N1FBS ","B1N1FBT ","B1N1FD ","B1N1FL ","B1N1FN ","B1N1FT ","B1N1FX ", &
"B1N1FY ","B1N1GAM ","B1N1M ","B1N1MBN ","B1N1MBS ","B1N1MBT ","B1N1MM ","B1N1PHI ", &
@@ -1930,10 +1930,10 @@ module AeroDyn_IO_Params
"B1N9FY ","B1N9GAM ","B1N9M ","B1N9MBN ","B1N9MBS ","B1N9MBT ","B1N9MM ","B1N9PHI ", &
"B1N9RE ","B1N9SGCAV","B1N9SIGCR","B1N9STVX ","B1N9STVY ","B1N9STVZ ","B1N9THETA","B1N9TNIND", &
"B1N9VDISX","B1N9VDISY","B1N9VDISZ","B1N9VINDX","B1N9VINDY","B1N9VREL ","B1N9VUNDX","B1N9VUNDY", &
- "B1N9VUNDZ","B1PITCH ","B2AEROFX ","B2AEROFXG","B2AEROFY ","B2AEROFYG","B2AEROFZ ","B2AEROFZG", &
- "B2AEROMX ","B2AEROMXG","B2AEROMY ","B2AEROMYG","B2AEROMZ ","B2AEROMZG","B2AEROPWR","B2AZIMUTH", &
- "B2FLDFX ","B2FLDFXG ","B2FLDFY ","B2FLDFYG ","B2FLDFZ ","B2FLDFZG ","B2FLDMX ","B2FLDMXG ", &
- "B2FLDMY ","B2FLDMYG ","B2FLDMZ ","B2FLDMZG ","B2FLDPWR ","B2N1ALPHA","B2N1AXIND","B2N1CD ", &
+ "B1N9VUNDZ","B1PITCH ","B2AEROFX ","B2AEROFXI","B2AEROFY ","B2AEROFYI","B2AEROFZ ","B2AEROFZI", &
+ "B2AEROMX ","B2AEROMXI","B2AEROMY ","B2AEROMYI","B2AEROMZ ","B2AEROMZI","B2AEROPWR","B2AZIMUTH", &
+ "B2FLDFX ","B2FLDFXI ","B2FLDFY ","B2FLDFYI ","B2FLDFZ ","B2FLDFZI ","B2FLDMX ","B2FLDMXI ", &
+ "B2FLDMY ","B2FLDMYI ","B2FLDMZ ","B2FLDMZI ","B2FLDPWR ","B2N1ALPHA","B2N1AXIND","B2N1CD ", &
"B2N1CL ","B2N1CLRNC","B2N1CM ","B2N1CN ","B2N1CPMIN","B2N1CT ","B2N1CURVE","B2N1CX ", &
"B2N1CY ","B2N1DYNP ","B2N1FBN ","B2N1FBS ","B2N1FBT ","B2N1FD ","B2N1FL ","B2N1FN ", &
"B2N1FT ","B2N1FX ","B2N1FY ","B2N1GAM ","B2N1M ","B2N1MBN ","B2N1MBS ","B2N1MBT ", &
@@ -1985,10 +1985,10 @@ module AeroDyn_IO_Params
"B2N9FT ","B2N9FX ","B2N9FY ","B2N9GAM ","B2N9M ","B2N9MBN ","B2N9MBS ","B2N9MBT ", &
"B2N9MM ","B2N9PHI ","B2N9RE ","B2N9SGCAV","B2N9SIGCR","B2N9STVX ","B2N9STVY ","B2N9STVZ ", &
"B2N9THETA","B2N9TNIND","B2N9VDISX","B2N9VDISY","B2N9VDISZ","B2N9VINDX","B2N9VINDY","B2N9VREL ", &
- "B2N9VUNDX","B2N9VUNDY","B2N9VUNDZ","B2PITCH ","B3AEROFX ","B3AEROFXG","B3AEROFY ","B3AEROFYG", &
- "B3AEROFZ ","B3AEROFZG","B3AEROMX ","B3AEROMXG","B3AEROMY ","B3AEROMYG","B3AEROMZ ","B3AEROMZG", &
- "B3AEROPWR","B3AZIMUTH","B3FLDFX ","B3FLDFXG ","B3FLDFY ","B3FLDFYG ","B3FLDFZ ","B3FLDFZG ", &
- "B3FLDMX ","B3FLDMXG ","B3FLDMY ","B3FLDMYG ","B3FLDMZ ","B3FLDMZG ","B3FLDPWR ","B3N1ALPHA", &
+ "B2N9VUNDX","B2N9VUNDY","B2N9VUNDZ","B2PITCH ","B3AEROFX ","B3AEROFXI","B3AEROFY ","B3AEROFYI", &
+ "B3AEROFZ ","B3AEROFZI","B3AEROMX ","B3AEROMXI","B3AEROMY ","B3AEROMYI","B3AEROMZ ","B3AEROMZI", &
+ "B3AEROPWR","B3AZIMUTH","B3FLDFX ","B3FLDFXI ","B3FLDFY ","B3FLDFYI ","B3FLDFZ ","B3FLDFZI ", &
+ "B3FLDMX ","B3FLDMXI ","B3FLDMY ","B3FLDMYI ","B3FLDMZ ","B3FLDMZI ","B3FLDPWR ","B3N1ALPHA", &
"B3N1AXIND","B3N1CD ","B3N1CL ","B3N1CLRNC","B3N1CM ","B3N1CN ","B3N1CPMIN","B3N1CT ", &
"B3N1CURVE","B3N1CX ","B3N1CY ","B3N1DYNP ","B3N1FBN ","B3N1FBS ","B3N1FBT ","B3N1FD ", &
"B3N1FL ","B3N1FN ","B3N1FT ","B3N1FX ","B3N1FY ","B3N1GAM ","B3N1M ","B3N1MBN ", &
@@ -2040,45 +2040,46 @@ module AeroDyn_IO_Params
"B3N9FL ","B3N9FN ","B3N9FT ","B3N9FX ","B3N9FY ","B3N9GAM ","B3N9M ","B3N9MBN ", &
"B3N9MBS ","B3N9MBT ","B3N9MM ","B3N9PHI ","B3N9RE ","B3N9SGCAV","B3N9SIGCR","B3N9STVX ", &
"B3N9STVY ","B3N9STVZ ","B3N9THETA","B3N9TNIND","B3N9VDISX","B3N9VDISY","B3N9VDISZ","B3N9VINDX", &
- "B3N9VINDY","B3N9VREL ","B3N9VUNDX","B3N9VUNDY","B3N9VUNDZ","B3PITCH ","B4AEROFX ","B4AEROFXG", &
- "B4AEROFY ","B4AEROFYG","B4AEROFZ ","B4AEROFZG","B4AEROMX ","B4AEROMXG","B4AEROMY ","B4AEROMYG", &
- "B4AEROMZ ","B4AEROMZG","B4AEROPWR","B4FLDFX ","B4FLDFXG ","B4FLDFY ","B4FLDFYG ","B4FLDFZ ", &
- "B4FLDFZG ","B4FLDMX ","B4FLDMXG ","B4FLDMY ","B4FLDMYG ","B4FLDMZ ","B4FLDMZG ","B4FLDPWR ", &
+ "B3N9VINDY","B3N9VREL ","B3N9VUNDX","B3N9VUNDY","B3N9VUNDZ","B3PITCH ","B4AEROFX ","B4AEROFXI", &
+ "B4AEROFY ","B4AEROFYI","B4AEROFZ ","B4AEROFZI","B4AEROMX ","B4AEROMXI","B4AEROMY ","B4AEROMYI", &
+ "B4AEROMZ ","B4AEROMZI","B4AEROPWR","B4FLDFX ","B4FLDFXI ","B4FLDFY ","B4FLDFYI ","B4FLDFZ ", &
+ "B4FLDFZI ","B4FLDMX ","B4FLDMXI ","B4FLDMY ","B4FLDMYI ","B4FLDMZ ","B4FLDMZI ","B4FLDPWR ", &
"DBEMTAU1 ","HBFBX ","HBFBY ","HBFBZ ","HBMBX ","HBMBY ","HBMBZ ","NCFBX ", &
"NCFBY ","NCFBZ ","NCMBX ","NCMBY ","NCMBZ ","RTAEROCP ","RTAEROCQ ","RTAEROCT ", &
- "RTAEROFXG","RTAEROFXH","RTAEROFYG","RTAEROFYH","RTAEROFZG","RTAEROFZH","RTAEROMXG","RTAEROMXH", &
- "RTAEROMYG","RTAEROMYH","RTAEROMZG","RTAEROMZH","RTAEROPWR","RTAREA ","RTFLDCP ","RTFLDCQ ", &
- "RTFLDCT ","RTFLDFXG ","RTFLDFXH ","RTFLDFYG ","RTFLDFYH ","RTFLDFZG ","RTFLDFZH ","RTFLDMXG ", &
- "RTFLDMXH ","RTFLDMYG ","RTFLDMYH ","RTFLDMZG ","RTFLDMZH ","RTFLDPWR ","RTSKEW ","RTSPEED ", &
- "RTTSR ","RTVAVGXH ","RTVAVGYH ","RTVAVGZH ","TFALPHA ","TFFXI ","TFFYI ","TFFZI ", &
- "TFMACH ","TFMXI ","TFMYI ","TFMZI ","TFRE ","TFSTVXI ","TFSTVYI ","TFSTVZI ", &
- "TFVINDXI ","TFVINDYI ","TFVINDZI ","TFVREL ","TFVRELXI ","TFVRELYI ","TFVRELZI ","TFVUNDXI ", &
- "TFVUNDYI ","TFVUNDZI ","TWN1DYNP ","TWN1FBX ","TWN1FBY ","TWN1FBZ ","TWN1FDX ","TWN1FDY ", &
- "TWN1M ","TWN1MBX ","TWN1MBY ","TWN1MBZ ","TWN1RE ","TWN1STVX ","TWN1STVY ","TWN1STVZ ", &
- "TWN1VREL ","TWN1VUNDX","TWN1VUNDY","TWN1VUNDZ","TWN2DYNP ","TWN2FBX ","TWN2FBY ","TWN2FBZ ", &
- "TWN2FDX ","TWN2FDY ","TWN2M ","TWN2MBX ","TWN2MBY ","TWN2MBZ ","TWN2RE ","TWN2STVX ", &
- "TWN2STVY ","TWN2STVZ ","TWN2VREL ","TWN2VUNDX","TWN2VUNDY","TWN2VUNDZ","TWN3DYNP ","TWN3FBX ", &
- "TWN3FBY ","TWN3FBZ ","TWN3FDX ","TWN3FDY ","TWN3M ","TWN3MBX ","TWN3MBY ","TWN3MBZ ", &
- "TWN3RE ","TWN3STVX ","TWN3STVY ","TWN3STVZ ","TWN3VREL ","TWN3VUNDX","TWN3VUNDY","TWN3VUNDZ", &
- "TWN4DYNP ","TWN4FBX ","TWN4FBY ","TWN4FBZ ","TWN4FDX ","TWN4FDY ","TWN4M ","TWN4MBX ", &
- "TWN4MBY ","TWN4MBZ ","TWN4RE ","TWN4STVX ","TWN4STVY ","TWN4STVZ ","TWN4VREL ","TWN4VUNDX", &
- "TWN4VUNDY","TWN4VUNDZ","TWN5DYNP ","TWN5FBX ","TWN5FBY ","TWN5FBZ ","TWN5FDX ","TWN5FDY ", &
- "TWN5M ","TWN5MBX ","TWN5MBY ","TWN5MBZ ","TWN5RE ","TWN5STVX ","TWN5STVY ","TWN5STVZ ", &
- "TWN5VREL ","TWN5VUNDX","TWN5VUNDY","TWN5VUNDZ","TWN6DYNP ","TWN6FBX ","TWN6FBY ","TWN6FBZ ", &
- "TWN6FDX ","TWN6FDY ","TWN6M ","TWN6MBX ","TWN6MBY ","TWN6MBZ ","TWN6RE ","TWN6STVX ", &
- "TWN6STVY ","TWN6STVZ ","TWN6VREL ","TWN6VUNDX","TWN6VUNDY","TWN6VUNDZ","TWN7DYNP ","TWN7FBX ", &
- "TWN7FBY ","TWN7FBZ ","TWN7FDX ","TWN7FDY ","TWN7M ","TWN7MBX ","TWN7MBY ","TWN7MBZ ", &
- "TWN7RE ","TWN7STVX ","TWN7STVY ","TWN7STVZ ","TWN7VREL ","TWN7VUNDX","TWN7VUNDY","TWN7VUNDZ", &
- "TWN8DYNP ","TWN8FBX ","TWN8FBY ","TWN8FBZ ","TWN8FDX ","TWN8FDY ","TWN8M ","TWN8MBX ", &
- "TWN8MBY ","TWN8MBZ ","TWN8RE ","TWN8STVX ","TWN8STVY ","TWN8STVZ ","TWN8VREL ","TWN8VUNDX", &
- "TWN8VUNDY","TWN8VUNDZ","TWN9DYNP ","TWN9FBX ","TWN9FBY ","TWN9FBZ ","TWN9FDX ","TWN9FDY ", &
- "TWN9M ","TWN9MBX ","TWN9MBY ","TWN9MBZ ","TWN9RE ","TWN9STVX ","TWN9STVY ","TWN9STVZ ", &
- "TWN9VREL ","TWN9VUNDX","TWN9VUNDY","TWN9VUNDZ"/)
- INTEGER(IntKi), PARAMETER :: ParamIndxAry(1588) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:)
- B1AeroFx , B1AeroFxg , B1AeroFy , B1AeroFyg , B1AeroFz , B1AeroFzg , B1AeroMx , B1AeroMxg , &
- B1AeroMy , B1AeroMyg , B1AeroMz , B1AeroMzg , B1AeroPwr , B1Azimuth , B1AeroFx , B1AeroFxg , &
- B1AeroFy , B1AeroFyg , B1AeroFz , B1AeroFzg , B1AeroMx , B1AeroMxg , B1AeroMy , B1AeroMyg , &
- B1AeroMz , B1AeroMzg , B1AeroPwr , B1N1Alpha , B1N1AxInd , B1N1Cd , B1N1Cl , B1N1Clrnc , &
+ "RTAEROFXH","RTAEROFXI","RTAEROFYH","RTAEROFYI","RTAEROFZH","RTAEROFZI","RTAEROMXH","RTAEROMXI", &
+ "RTAEROMYH","RTAEROMYI","RTAEROMZH","RTAEROMZI","RTAEROPWR","RTAREA ","RTFLDCP ","RTFLDCQ ", &
+ "RTFLDCT ","RTFLDFXG ","RTFLDFXH ","RTFLDFXI ","RTFLDFYG ","RTFLDFYH ","RTFLDFYI ","RTFLDFZG ", &
+ "RTFLDFZH ","RTFLDFZI ","RTFLDMXG ","RTFLDMXH ","RTFLDMXI ","RTFLDMYG ","RTFLDMYH ","RTFLDMYI ", &
+ "RTFLDMZG ","RTFLDMZH ","RTFLDMZI ","RTFLDPWR ","RTSKEW ","RTSPEED ","RTTSR ","RTVAVGXH ", &
+ "RTVAVGYH ","RTVAVGZH ","TFALPHA ","TFFXI ","TFFYI ","TFFZI ","TFMACH ","TFMXI ", &
+ "TFMYI ","TFMZI ","TFRE ","TFSTVXI ","TFSTVYI ","TFSTVZI ","TFVINDXI ","TFVINDYI ", &
+ "TFVINDZI ","TFVREL ","TFVRELXI ","TFVRELYI ","TFVRELZI ","TFVUNDXI ","TFVUNDYI ","TFVUNDZI ", &
+ "TWN1DYNP ","TWN1FBX ","TWN1FBY ","TWN1FBZ ","TWN1FDX ","TWN1FDY ","TWN1M ","TWN1MBX ", &
+ "TWN1MBY ","TWN1MBZ ","TWN1RE ","TWN1STVX ","TWN1STVY ","TWN1STVZ ","TWN1VREL ","TWN1VUNDX", &
+ "TWN1VUNDY","TWN1VUNDZ","TWN2DYNP ","TWN2FBX ","TWN2FBY ","TWN2FBZ ","TWN2FDX ","TWN2FDY ", &
+ "TWN2M ","TWN2MBX ","TWN2MBY ","TWN2MBZ ","TWN2RE ","TWN2STVX ","TWN2STVY ","TWN2STVZ ", &
+ "TWN2VREL ","TWN2VUNDX","TWN2VUNDY","TWN2VUNDZ","TWN3DYNP ","TWN3FBX ","TWN3FBY ","TWN3FBZ ", &
+ "TWN3FDX ","TWN3FDY ","TWN3M ","TWN3MBX ","TWN3MBY ","TWN3MBZ ","TWN3RE ","TWN3STVX ", &
+ "TWN3STVY ","TWN3STVZ ","TWN3VREL ","TWN3VUNDX","TWN3VUNDY","TWN3VUNDZ","TWN4DYNP ","TWN4FBX ", &
+ "TWN4FBY ","TWN4FBZ ","TWN4FDX ","TWN4FDY ","TWN4M ","TWN4MBX ","TWN4MBY ","TWN4MBZ ", &
+ "TWN4RE ","TWN4STVX ","TWN4STVY ","TWN4STVZ ","TWN4VREL ","TWN4VUNDX","TWN4VUNDY","TWN4VUNDZ", &
+ "TWN5DYNP ","TWN5FBX ","TWN5FBY ","TWN5FBZ ","TWN5FDX ","TWN5FDY ","TWN5M ","TWN5MBX ", &
+ "TWN5MBY ","TWN5MBZ ","TWN5RE ","TWN5STVX ","TWN5STVY ","TWN5STVZ ","TWN5VREL ","TWN5VUNDX", &
+ "TWN5VUNDY","TWN5VUNDZ","TWN6DYNP ","TWN6FBX ","TWN6FBY ","TWN6FBZ ","TWN6FDX ","TWN6FDY ", &
+ "TWN6M ","TWN6MBX ","TWN6MBY ","TWN6MBZ ","TWN6RE ","TWN6STVX ","TWN6STVY ","TWN6STVZ ", &
+ "TWN6VREL ","TWN6VUNDX","TWN6VUNDY","TWN6VUNDZ","TWN7DYNP ","TWN7FBX ","TWN7FBY ","TWN7FBZ ", &
+ "TWN7FDX ","TWN7FDY ","TWN7M ","TWN7MBX ","TWN7MBY ","TWN7MBZ ","TWN7RE ","TWN7STVX ", &
+ "TWN7STVY ","TWN7STVZ ","TWN7VREL ","TWN7VUNDX","TWN7VUNDY","TWN7VUNDZ","TWN8DYNP ","TWN8FBX ", &
+ "TWN8FBY ","TWN8FBZ ","TWN8FDX ","TWN8FDY ","TWN8M ","TWN8MBX ","TWN8MBY ","TWN8MBZ ", &
+ "TWN8RE ","TWN8STVX ","TWN8STVY ","TWN8STVZ ","TWN8VREL ","TWN8VUNDX","TWN8VUNDY","TWN8VUNDZ", &
+ "TWN9DYNP ","TWN9FBX ","TWN9FBY ","TWN9FBZ ","TWN9FDX ","TWN9FDY ","TWN9M ","TWN9MBX ", &
+ "TWN9MBY ","TWN9MBZ ","TWN9RE ","TWN9STVX ","TWN9STVY ","TWN9STVZ ","TWN9VREL ","TWN9VUNDX", &
+ "TWN9VUNDY","TWN9VUNDZ"/)
+ INTEGER(IntKi), PARAMETER :: ParamIndxAry(1594) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:)
+ B1AeroFx , B1AeroFxi , B1AeroFy , B1AeroFyi , B1AeroFz , B1AeroFzi , B1AeroMx , B1AeroMxi , &
+ B1AeroMy , B1AeroMyi , B1AeroMz , B1AeroMzi , B1AeroPwr , B1Azimuth , B1AeroFx , B1AeroFxi , &
+ B1AeroFy , B1AeroFyi , B1AeroFz , B1AeroFzi , B1AeroMx , B1AeroMxi , B1AeroMy , B1AeroMyi , &
+ B1AeroMz , B1AeroMzi , B1AeroPwr , B1N1Alpha , B1N1AxInd , B1N1Cd , B1N1Cl , B1N1Clrnc , &
B1N1Cm , B1N1Cn , B1N1Cpmin , B1N1Ct , B1N1Curve , B1N1Cx , B1N1Cy , B1N1DynP , &
B1N1Fbn , B1N1Fbs , B1N1Fbt , B1N1Fd , B1N1Fl , B1N1Fn , B1N1Ft , B1N1Fx , &
B1N1Fy , B1N1Gam , B1N1M , B1N1Mbn , B1N1Mbs , B1N1Mbt , B1N1Mm , B1N1Phi , &
@@ -2130,10 +2131,10 @@ module AeroDyn_IO_Params
B1N9Fy , B1N9Gam , B1N9M , B1N9Mbn , B1N9Mbs , B1N9Mbt , B1N9Mm , B1N9Phi , &
B1N9Re , B1N9SgCav , B1N9SigCr , B1N9STVx , B1N9STVy , B1N9STVz , B1N9Theta , B1N9TnInd , &
B1N9VDisx , B1N9VDisy , B1N9VDisz , B1N9Vindx , B1N9Vindy , B1N9VRel , B1N9VUndx , B1N9VUndy , &
- B1N9VUndz , B1Pitch , B2AeroFx , B2AeroFxg , B2AeroFy , B2AeroFyg , B2AeroFz , B2AeroFzg , &
- B2AeroMx , B2AeroMxg , B2AeroMy , B2AeroMyg , B2AeroMz , B2AeroMzg , B2AeroPwr , B2Azimuth , &
- B2AeroFx , B2AeroFxg , B2AeroFy , B2AeroFyg , B2AeroFz , B2AeroFzg , B2AeroMx , B2AeroMxg , &
- B2AeroMy , B2AeroMyg , B2AeroMz , B2AeroMzg , B2AeroPwr , B2N1Alpha , B2N1AxInd , B2N1Cd , &
+ B1N9VUndz , B1Pitch , B2AeroFx , B2AeroFxi , B2AeroFy , B2AeroFyi , B2AeroFz , B2AeroFzi , &
+ B2AeroMx , B2AeroMxi , B2AeroMy , B2AeroMyi , B2AeroMz , B2AeroMzi , B2AeroPwr , B2Azimuth , &
+ B2AeroFx , B2AeroFxi , B2AeroFy , B2AeroFyi , B2AeroFz , B2AeroFzi , B2AeroMx , B2AeroMxi , &
+ B2AeroMy , B2AeroMyi , B2AeroMz , B2AeroMzi , B2AeroPwr , B2N1Alpha , B2N1AxInd , B2N1Cd , &
B2N1Cl , B2N1Clrnc , B2N1Cm , B2N1Cn , B2N1Cpmin , B2N1Ct , B2N1Curve , B2N1Cx , &
B2N1Cy , B2N1DynP , B2N1Fbn , B2N1Fbs , B2N1Fbt , B2N1Fd , B2N1Fl , B2N1Fn , &
B2N1Ft , B2N1Fx , B2N1Fy , B2N1Gam , B2N1M , B2N1Mbn , B2N1Mbs , B2N1Mbt , &
@@ -2185,10 +2186,10 @@ module AeroDyn_IO_Params
B2N9Ft , B2N9Fx , B2N9Fy , B2N9Gam , B2N9M , B2N9Mbn , B2N9Mbs , B2N9Mbt , &
B2N9Mm , B2N9Phi , B2N9Re , B2N9SgCav , B2N9SigCr , B2N9STVx , B2N9STVy , B2N9STVz , &
B2N9Theta , B2N9TnInd , B2N9VDisx , B2N9VDisy , B2N9VDisz , B2N9Vindx , B2N9Vindy , B2N9VRel , &
- B2N9VUndx , B2N9VUndy , B2N9VUndz , B2Pitch , B3AeroFx , B3AeroFxg , B3AeroFy , B3AeroFyg , &
- B3AeroFz , B3AeroFzg , B3AeroMx , B3AeroMxg , B3AeroMy , B3AeroMyg , B3AeroMz , B3AeroMzg , &
- B3AeroPwr , B3Azimuth , B3AeroFx , B3AeroFxg , B3AeroFy , B3AeroFyg , B3AeroFz , B3AeroFzg , &
- B3AeroMx , B3AeroMxg , B3AeroMy , B3AeroMyg , B3AeroMz , B3AeroMzg , B3AeroPwr , B3N1Alpha , &
+ B2N9VUndx , B2N9VUndy , B2N9VUndz , B2Pitch , B3AeroFx , B3AeroFxi , B3AeroFy , B3AeroFyi , &
+ B3AeroFz , B3AeroFzi , B3AeroMx , B3AeroMxi , B3AeroMy , B3AeroMyi , B3AeroMz , B3AeroMzi , &
+ B3AeroPwr , B3Azimuth , B3AeroFx , B3AeroFxi , B3AeroFy , B3AeroFyi , B3AeroFz , B3AeroFzi , &
+ B3AeroMx , B3AeroMxi , B3AeroMy , B3AeroMyi , B3AeroMz , B3AeroMzi , B3AeroPwr , B3N1Alpha , &
B3N1AxInd , B3N1Cd , B3N1Cl , B3N1Clrnc , B3N1Cm , B3N1Cn , B3N1Cpmin , B3N1Ct , &
B3N1Curve , B3N1Cx , B3N1Cy , B3N1DynP , B3N1Fbn , B3N1Fbs , B3N1Fbt , B3N1Fd , &
B3N1Fl , B3N1Fn , B3N1Ft , B3N1Fx , B3N1Fy , B3N1Gam , B3N1M , B3N1Mbn , &
@@ -2240,41 +2241,42 @@ module AeroDyn_IO_Params
B3N9Fl , B3N9Fn , B3N9Ft , B3N9Fx , B3N9Fy , B3N9Gam , B3N9M , B3N9Mbn , &
B3N9Mbs , B3N9Mbt , B3N9Mm , B3N9Phi , B3N9Re , B3N9SgCav , B3N9SigCr , B3N9STVx , &
B3N9STVy , B3N9STVz , B3N9Theta , B3N9TnInd , B3N9VDisx , B3N9VDisy , B3N9VDisz , B3N9Vindx , &
- B3N9Vindy , B3N9VRel , B3N9VUndx , B3N9VUndy , B3N9VUndz , B3Pitch , B4AeroFx , B4AeroFxg , &
- B4AeroFy , B4AeroFyg , B4AeroFz , B4AeroFzg , B4AeroMx , B4AeroMxg , B4AeroMy , B4AeroMyg , &
- B4AeroMz , B4AeroMzg , B4AeroPwr , B4AeroFx , B4AeroFxg , B4AeroFy , B4AeroFyg , B4AeroFz , &
- B4AeroFzg , B4AeroMx , B4AeroMxg , B4AeroMy , B4AeroMyg , B4AeroMz , B4AeroMzg , B4AeroPwr , &
+ B3N9Vindy , B3N9VRel , B3N9VUndx , B3N9VUndy , B3N9VUndz , B3Pitch , B4AeroFx , B4AeroFxi , &
+ B4AeroFy , B4AeroFyi , B4AeroFz , B4AeroFzi , B4AeroMx , B4AeroMxi , B4AeroMy , B4AeroMyi , &
+ B4AeroMz , B4AeroMzi , B4AeroPwr , B4AeroFx , B4AeroFxi , B4AeroFy , B4AeroFyi , B4AeroFz , &
+ B4AeroFzi , B4AeroMx , B4AeroMxi , B4AeroMy , B4AeroMyi , B4AeroMz , B4AeroMzi , B4AeroPwr , &
DBEMTau1 , HbFbx , HbFby , HbFbz , HbMbx , HbMby , HbMbz , NcFbx , &
NcFby , NcFbz , NcMbx , NcMby , NcMbz , RtAeroCp , RtAeroCq , RtAeroCt , &
- RtAeroFxg , RtAeroFxh , RtAeroFyg , RtAeroFyh , RtAeroFzg , RtAeroFzh , RtAeroMxg , RtAeroMxh , &
- RtAeroMyg , RtAeroMyh , RtAeroMzg , RtAeroMzh , RtAeroPwr , RtArea , RtAeroCp , RtAeroCq , &
- RtAeroCt , RtAeroFxg , RtAeroFxh , RtAeroFyg , RtAeroFyh , RtAeroFzg , RtAeroFzh , RtAeroMxg , &
- RtAeroMxh , RtAeroMyg , RtAeroMyh , RtAeroMzg , RtAeroMzh , RtAeroPwr , RtSkew , RtSpeed , &
- RtTSR , RtVAvgxh , RtVAvgyh , RtVAvgzh , TFAlpha , TFFxi , TFFyi , TFFzi , &
- TFMach , TFMxi , TFMyi , TFMzi , TFRe , TFSTVxi , TFSTVyi , TFSTVzi , &
- TFVindxi , TFVindyi , TFVindzi , TFVrel , TFVrelxi , TFVrelyi , TFVrelzi , TFVundxi , &
- TFVundyi , TFVundzi , TwN1DynP , TwN1Fbx , TwN1Fby , TwN1Fbz , TwN1Fdx , TwN1Fdy , &
- TwN1M , TwN1Mbx , TwN1Mby , TwN1Mbz , TwN1Re , TwN1STVx , TwN1STVy , TwN1STVz , &
- TwN1Vrel , TwN1VUndx , TwN1VUndy , TwN1VUndz , TwN2DynP , TwN2Fbx , TwN2Fby , TwN2Fbz , &
- TwN2Fdx , TwN2Fdy , TwN2M , TwN2Mbx , TwN2Mby , TwN2Mbz , TwN2Re , TwN2STVx , &
- TwN2STVy , TwN2STVz , TwN2Vrel , TwN2VUndx , TwN2VUndy , TwN2VUndz , TwN3DynP , TwN3Fbx , &
- TwN3Fby , TwN3Fbz , TwN3Fdx , TwN3Fdy , TwN3M , TwN3Mbx , TwN3Mby , TwN3Mbz , &
- TwN3Re , TwN3STVx , TwN3STVy , TwN3STVz , TwN3Vrel , TwN3VUndx , TwN3VUndy , TwN3VUndz , &
- TwN4DynP , TwN4Fbx , TwN4Fby , TwN4Fbz , TwN4Fdx , TwN4Fdy , TwN4M , TwN4Mbx , &
- TwN4Mby , TwN4Mbz , TwN4Re , TwN4STVx , TwN4STVy , TwN4STVz , TwN4Vrel , TwN4VUndx , &
- TwN4VUndy , TwN4VUndz , TwN5DynP , TwN5Fbx , TwN5Fby , TwN5Fbz , TwN5Fdx , TwN5Fdy , &
- TwN5M , TwN5Mbx , TwN5Mby , TwN5Mbz , TwN5Re , TwN5STVx , TwN5STVy , TwN5STVz , &
- TwN5Vrel , TwN5VUndx , TwN5VUndy , TwN5VUndz , TwN6DynP , TwN6Fbx , TwN6Fby , TwN6Fbz , &
- TwN6Fdx , TwN6Fdy , TwN6M , TwN6Mbx , TwN6Mby , TwN6Mbz , TwN6Re , TwN6STVx , &
- TwN6STVy , TwN6STVz , TwN6Vrel , TwN6VUndx , TwN6VUndy , TwN6VUndz , TwN7DynP , TwN7Fbx , &
- TwN7Fby , TwN7Fbz , TwN7Fdx , TwN7Fdy , TwN7M , TwN7Mbx , TwN7Mby , TwN7Mbz , &
- TwN7Re , TwN7STVx , TwN7STVy , TwN7STVz , TwN7Vrel , TwN7VUndx , TwN7VUndy , TwN7VUndz , &
- TwN8DynP , TwN8Fbx , TwN8Fby , TwN8Fbz , TwN8Fdx , TwN8Fdy , TwN8M , TwN8Mbx , &
- TwN8Mby , TwN8Mbz , TwN8Re , TwN8STVx , TwN8STVy , TwN8STVz , TwN8Vrel , TwN8VUndx , &
- TwN8VUndy , TwN8VUndz , TwN9DynP , TwN9Fbx , TwN9Fby , TwN9Fbz , TwN9Fdx , TwN9Fdy , &
- TwN9M , TwN9Mbx , TwN9Mby , TwN9Mbz , TwN9Re , TwN9STVx , TwN9STVy , TwN9STVz , &
- TwN9Vrel , TwN9VUndx , TwN9VUndy , TwN9VUndz /)
- CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(1588) = (/ & ! This lists the units corresponding to the allowed parameters
+ RtAeroFxh , RtAeroFxi , RtAeroFyh , RtAeroFyi , RtAeroFzh , RtAeroFzi , RtAeroMxh , RtAeroMxi , &
+ RtAeroMyh , RtAeroMyi , RtAeroMzh , RtAeroMzi , RtAeroPwr , RtArea , RtAeroCp , RtAeroCq , &
+ RtAeroCt , RtAeroFxi , RtAeroFxh , RtAeroFxi , RtAeroFyi , RtAeroFyh , RtAeroFyi , RtAeroFzi , &
+ RtAeroFzh , RtAeroFzi , RtAeroMxi , RtAeroMxh , RtAeroMxi , RtAeroMyi , RtAeroMyh , RtAeroMyi , &
+ RtAeroMzi , RtAeroMzh , RtAeroMzi , RtAeroPwr , RtSkew , RtSpeed , RtTSR , RtVAvgxh , &
+ RtVAvgyh , RtVAvgzh , TFAlpha , TFFxi , TFFyi , TFFzi , TFMach , TFMxi , &
+ TFMyi , TFMzi , TFRe , TFSTVxi , TFSTVyi , TFSTVzi , TFVindxi , TFVindyi , &
+ TFVindzi , TFVrel , TFVrelxi , TFVrelyi , TFVrelzi , TFVundxi , TFVundyi , TFVundzi , &
+ TwN1DynP , TwN1Fbx , TwN1Fby , TwN1Fbz , TwN1Fdx , TwN1Fdy , TwN1M , TwN1Mbx , &
+ TwN1Mby , TwN1Mbz , TwN1Re , TwN1STVx , TwN1STVy , TwN1STVz , TwN1Vrel , TwN1VUndx , &
+ TwN1VUndy , TwN1VUndz , TwN2DynP , TwN2Fbx , TwN2Fby , TwN2Fbz , TwN2Fdx , TwN2Fdy , &
+ TwN2M , TwN2Mbx , TwN2Mby , TwN2Mbz , TwN2Re , TwN2STVx , TwN2STVy , TwN2STVz , &
+ TwN2Vrel , TwN2VUndx , TwN2VUndy , TwN2VUndz , TwN3DynP , TwN3Fbx , TwN3Fby , TwN3Fbz , &
+ TwN3Fdx , TwN3Fdy , TwN3M , TwN3Mbx , TwN3Mby , TwN3Mbz , TwN3Re , TwN3STVx , &
+ TwN3STVy , TwN3STVz , TwN3Vrel , TwN3VUndx , TwN3VUndy , TwN3VUndz , TwN4DynP , TwN4Fbx , &
+ TwN4Fby , TwN4Fbz , TwN4Fdx , TwN4Fdy , TwN4M , TwN4Mbx , TwN4Mby , TwN4Mbz , &
+ TwN4Re , TwN4STVx , TwN4STVy , TwN4STVz , TwN4Vrel , TwN4VUndx , TwN4VUndy , TwN4VUndz , &
+ TwN5DynP , TwN5Fbx , TwN5Fby , TwN5Fbz , TwN5Fdx , TwN5Fdy , TwN5M , TwN5Mbx , &
+ TwN5Mby , TwN5Mbz , TwN5Re , TwN5STVx , TwN5STVy , TwN5STVz , TwN5Vrel , TwN5VUndx , &
+ TwN5VUndy , TwN5VUndz , TwN6DynP , TwN6Fbx , TwN6Fby , TwN6Fbz , TwN6Fdx , TwN6Fdy , &
+ TwN6M , TwN6Mbx , TwN6Mby , TwN6Mbz , TwN6Re , TwN6STVx , TwN6STVy , TwN6STVz , &
+ TwN6Vrel , TwN6VUndx , TwN6VUndy , TwN6VUndz , TwN7DynP , TwN7Fbx , TwN7Fby , TwN7Fbz , &
+ TwN7Fdx , TwN7Fdy , TwN7M , TwN7Mbx , TwN7Mby , TwN7Mbz , TwN7Re , TwN7STVx , &
+ TwN7STVy , TwN7STVz , TwN7Vrel , TwN7VUndx , TwN7VUndy , TwN7VUndz , TwN8DynP , TwN8Fbx , &
+ TwN8Fby , TwN8Fbz , TwN8Fdx , TwN8Fdy , TwN8M , TwN8Mbx , TwN8Mby , TwN8Mbz , &
+ TwN8Re , TwN8STVx , TwN8STVy , TwN8STVz , TwN8Vrel , TwN8VUndx , TwN8VUndy , TwN8VUndz , &
+ TwN9DynP , TwN9Fbx , TwN9Fby , TwN9Fbz , TwN9Fdx , TwN9Fdy , TwN9M , TwN9Mbx , &
+ TwN9Mby , TwN9Mbz , TwN9Re , TwN9STVx , TwN9STVy , TwN9STVz , TwN9Vrel , TwN9VUndx , &
+ TwN9VUndy , TwN9VUndz /)
+ CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(1594) = (/ character(ChanLen) :: & ! This lists the units corresponding to the allowed parameters
"(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", &
"(N-m) ","(N-m) ","(N-m) ","(N-m) ","(W) ","(deg) ","(N) ","(N) ", &
"(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", &
@@ -2448,11 +2450,14 @@ module AeroDyn_IO_Params
"(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(-) ","(-) ","(-) ", &
"(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ","(N-m) ", &
"(N-m) ","(N-m) ","(N-m) ","(N-m) ","(W) ","(m^2) ","(-) ","(-) ", &
- "(-) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N-m) ", &
- "(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(W) ","(deg) ","(rpm) ", &
- "(-) ","(m/s) ","(m/s) ","(m/s) ","(deg) ","(N) ","(N) ","(N) ", &
- "(-) ","(N-m) ","(N-m) ","(N-m) ","(-) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(-) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ","(N) ", &
+ "(N) ","(N) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ","(N-m) ", &
+ "(N-m) ","(N-m) ","(N-m) ","(W) ","(deg) ","(rpm) ","(-) ","(m/s) ", &
+ "(m/s) ","(m/s) ","(deg) ","(N) ","(N) ","(N) ","(-) ","(N-m) ", &
+ "(N-m) ","(N-m) ","(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
"(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
+ "(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(-) ","(N-m/m)", &
+ "(N-m/m)","(N-m/m)","(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
"(m/s) ","(m/s) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", &
"(-) ","(N-m/m)","(N-m/m)","(N-m/m)","(-) ","(m/s) ","(m/s) ","(m/s) ", &
"(m/s) ","(m/s) ","(m/s) ","(m/s) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ", &
@@ -2471,9 +2476,7 @@ module AeroDyn_IO_Params
"(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
"(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(-) ","(N-m/m)", &
"(N-m/m)","(N-m/m)","(-) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", &
- "(m/s) ","(m/s) ","(Pa) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ","(N/m) ", &
- "(-) ","(N-m/m)","(N-m/m)","(N-m/m)","(-) ","(m/s) ","(m/s) ","(m/s) ", &
- "(m/s) ","(m/s) ","(m/s) ","(m/s) "/)
+ "(m/s) ","(m/s) "/)
end module AeroDyn_IO_Params
diff --git a/modules/aerodyn/src/AeroDyn_Registry.txt b/modules/aerodyn/src/AeroDyn_Registry.txt
index 441e24f6a1..5f763c8a6c 100644
--- a/modules/aerodyn/src/AeroDyn_Registry.txt
+++ b/modules/aerodyn/src/AeroDyn_Registry.txt
@@ -263,6 +263,7 @@ typedef ^ RotMiscVarType AA_InputType AA_u - - - "Inputs to the AA module" -
typedef ^ RotMiscVarType ReKi DisturbedInflow {:}{:}{:} - - "InflowOnBlade values modified by tower influence" m/s
typedef ^ RotMiscVarType R8Ki orientationAnnulus {:}{:}{:}{:} - - "Coordinate system equivalent to BladeMotion Orientation, but without live sweep, blade-pitch, and twist angles" -
+typedef ^ RotMiscVarType R8Ki R_li {:}{:}{:}{:} - - "Transformation matrix from inertial system to the staggered polar coordinate system of a given section" -
typedef ^ RotMiscVarType ReKi AllOuts {:} - - "An array holding the value of all of the calculated (not only selected) output channels" -
typedef ^ RotMiscVarType ReKi W_Twr {:} - - "relative wind speed normal to the tower at node j" m/s
typedef ^ RotMiscVarType ReKi X_Twr {:} - - "local x-component of force per unit length of the jth node in the tower" m/s
@@ -276,6 +277,7 @@ typedef ^ RotMiscVarType ReKi M {:}{:} - - "pitching moment per unit length of t
typedef ^ RotMiscVarType ReKi Mx {:}{:} - - "pitching moment per unit length of the jth node in the kth blade (in x direction)" Nm/m
typedef ^ RotMiscVarType ReKi My {:}{:} - - "pitching moment per unit length of the jth node in the kth blade (in y direction)" Nm/m
typedef ^ RotMiscVarType ReKi Mz {:}{:} - - "pitching moment per unit length of the jth node in the kth blade (in z direction)" Nm/m
+typedef ^ RotMiscVarType ReKi Vind_i {:}{:}{:} - - "Induced velocities at jth node and kth blade (3xnSpanxnB)" m/s
typedef ^ RotMiscVarType ReKi V_DiskAvg {3} - - "disk-average relative wind speed" m/s
typedef ^ RotMiscVarType ReKi yaw - - - "Yaw calculated in SetInputsForBEMT" rad
typedef ^ RotMiscVarType ReKi tilt - - - "tilt calculated in SetInputsForBEMT" rad
@@ -286,8 +288,6 @@ typedef ^ RotMiscVarType MeshMapType B_L_2_H_P {:} - - "mapping data structure t
typedef ^ RotMiscVarType ReKi SigmaCavitCrit {:}{:} - - "critical cavitation number- inception value (above which cavit will occur)" -
typedef ^ RotMiscVarType ReKi SigmaCavit {:}{:} - - "cavitation number at node " -
typedef ^ RotMiscVarType Logical CavitWarnSet {:}{:} - - "cavitation warning issued " -
-typedef ^ RotMiscVarType ReKi BlFB {:}{:}{:} - - "buoyant force per unit length at blade node" N/m
-typedef ^ RotMiscVarType ReKi BlMB {:}{:}{:} - - "buoyant moment per unit length at blade node" Nm/m
typedef ^ RotMiscVarType ReKi TwrFB {:}{:} - - "buoyant force per unit length at tower node" N/m
typedef ^ RotMiscVarType ReKi TwrMB {:}{:} - - "buoyant moment per unit length at tower node" Nm/m
typedef ^ RotMiscVarType ReKi HubFB {:} - - "buoyant force at hub node" N
diff --git a/modules/aerodyn/src/AeroDyn_Types.f90 b/modules/aerodyn/src/AeroDyn_Types.f90
index 77135b3b37..c26eef9940 100644
--- a/modules/aerodyn/src/AeroDyn_Types.f90
+++ b/modules/aerodyn/src/AeroDyn_Types.f90
@@ -303,6 +303,7 @@ MODULE AeroDyn_Types
TYPE(AA_InputType) :: AA_u !< Inputs to the AA module [-]
REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: DisturbedInflow !< InflowOnBlade values modified by tower influence [m/s]
REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: orientationAnnulus !< Coordinate system equivalent to BladeMotion Orientation, but without live sweep, blade-pitch, and twist angles [-]
+ REAL(R8Ki) , DIMENSION(:,:,:,:), ALLOCATABLE :: R_li !< Transformation matrix from inertial system to the staggered polar coordinate system of a given section [-]
REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: AllOuts !< An array holding the value of all of the calculated (not only selected) output channels [-]
REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: W_Twr !< relative wind speed normal to the tower at node j [m/s]
REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: X_Twr !< local x-component of force per unit length of the jth node in the tower [m/s]
@@ -316,6 +317,7 @@ MODULE AeroDyn_Types
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Mx !< pitching moment per unit length of the jth node in the kth blade (in x direction) [Nm/m]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: My !< pitching moment per unit length of the jth node in the kth blade (in y direction) [Nm/m]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Mz !< pitching moment per unit length of the jth node in the kth blade (in z direction) [Nm/m]
+ REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: Vind_i !< Induced velocities at jth node and kth blade (3xnSpanxnB) [m/s]
REAL(ReKi) , DIMENSION(1:3) :: V_DiskAvg !< disk-average relative wind speed [m/s]
REAL(ReKi) :: yaw !< Yaw calculated in SetInputsForBEMT [rad]
REAL(ReKi) :: tilt !< tilt calculated in SetInputsForBEMT [rad]
@@ -326,8 +328,6 @@ MODULE AeroDyn_Types
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SigmaCavitCrit !< critical cavitation number- inception value (above which cavit will occur) [-]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: SigmaCavit !< cavitation number at node [-]
LOGICAL , DIMENSION(:,:), ALLOCATABLE :: CavitWarnSet !< cavitation warning issued [-]
- REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: BlFB !< buoyant force per unit length at blade node [N/m]
- REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: BlMB !< buoyant moment per unit length at blade node [Nm/m]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TwrFB !< buoyant force per unit length at tower node [N/m]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: TwrMB !< buoyant moment per unit length at tower node [Nm/m]
REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: HubFB !< buoyant force at hub node [N]
@@ -8892,6 +8892,24 @@ SUBROUTINE AD_CopyRotMiscVarType( SrcRotMiscVarTypeData, DstRotMiscVarTypeData,
END IF
DstRotMiscVarTypeData%orientationAnnulus = SrcRotMiscVarTypeData%orientationAnnulus
ENDIF
+IF (ALLOCATED(SrcRotMiscVarTypeData%R_li)) THEN
+ i1_l = LBOUND(SrcRotMiscVarTypeData%R_li,1)
+ i1_u = UBOUND(SrcRotMiscVarTypeData%R_li,1)
+ i2_l = LBOUND(SrcRotMiscVarTypeData%R_li,2)
+ i2_u = UBOUND(SrcRotMiscVarTypeData%R_li,2)
+ i3_l = LBOUND(SrcRotMiscVarTypeData%R_li,3)
+ i3_u = UBOUND(SrcRotMiscVarTypeData%R_li,3)
+ i4_l = LBOUND(SrcRotMiscVarTypeData%R_li,4)
+ i4_u = UBOUND(SrcRotMiscVarTypeData%R_li,4)
+ IF (.NOT. ALLOCATED(DstRotMiscVarTypeData%R_li)) THEN
+ ALLOCATE(DstRotMiscVarTypeData%R_li(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRotMiscVarTypeData%R_li.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstRotMiscVarTypeData%R_li = SrcRotMiscVarTypeData%R_li
+ENDIF
IF (ALLOCATED(SrcRotMiscVarTypeData%AllOuts)) THEN
i1_l = LBOUND(SrcRotMiscVarTypeData%AllOuts,1)
i1_u = UBOUND(SrcRotMiscVarTypeData%AllOuts,1)
@@ -9065,6 +9083,22 @@ SUBROUTINE AD_CopyRotMiscVarType( SrcRotMiscVarTypeData, DstRotMiscVarTypeData,
END IF
END IF
DstRotMiscVarTypeData%Mz = SrcRotMiscVarTypeData%Mz
+ENDIF
+IF (ALLOCATED(SrcRotMiscVarTypeData%Vind_i)) THEN
+ i1_l = LBOUND(SrcRotMiscVarTypeData%Vind_i,1)
+ i1_u = UBOUND(SrcRotMiscVarTypeData%Vind_i,1)
+ i2_l = LBOUND(SrcRotMiscVarTypeData%Vind_i,2)
+ i2_u = UBOUND(SrcRotMiscVarTypeData%Vind_i,2)
+ i3_l = LBOUND(SrcRotMiscVarTypeData%Vind_i,3)
+ i3_u = UBOUND(SrcRotMiscVarTypeData%Vind_i,3)
+ IF (.NOT. ALLOCATED(DstRotMiscVarTypeData%Vind_i)) THEN
+ ALLOCATE(DstRotMiscVarTypeData%Vind_i(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRotMiscVarTypeData%Vind_i.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstRotMiscVarTypeData%Vind_i = SrcRotMiscVarTypeData%Vind_i
ENDIF
DstRotMiscVarTypeData%V_DiskAvg = SrcRotMiscVarTypeData%V_DiskAvg
DstRotMiscVarTypeData%yaw = SrcRotMiscVarTypeData%yaw
@@ -9143,38 +9177,6 @@ SUBROUTINE AD_CopyRotMiscVarType( SrcRotMiscVarTypeData, DstRotMiscVarTypeData,
END IF
DstRotMiscVarTypeData%CavitWarnSet = SrcRotMiscVarTypeData%CavitWarnSet
ENDIF
-IF (ALLOCATED(SrcRotMiscVarTypeData%BlFB)) THEN
- i1_l = LBOUND(SrcRotMiscVarTypeData%BlFB,1)
- i1_u = UBOUND(SrcRotMiscVarTypeData%BlFB,1)
- i2_l = LBOUND(SrcRotMiscVarTypeData%BlFB,2)
- i2_u = UBOUND(SrcRotMiscVarTypeData%BlFB,2)
- i3_l = LBOUND(SrcRotMiscVarTypeData%BlFB,3)
- i3_u = UBOUND(SrcRotMiscVarTypeData%BlFB,3)
- IF (.NOT. ALLOCATED(DstRotMiscVarTypeData%BlFB)) THEN
- ALLOCATE(DstRotMiscVarTypeData%BlFB(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2)
- IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRotMiscVarTypeData%BlFB.', ErrStat, ErrMsg,RoutineName)
- RETURN
- END IF
- END IF
- DstRotMiscVarTypeData%BlFB = SrcRotMiscVarTypeData%BlFB
-ENDIF
-IF (ALLOCATED(SrcRotMiscVarTypeData%BlMB)) THEN
- i1_l = LBOUND(SrcRotMiscVarTypeData%BlMB,1)
- i1_u = UBOUND(SrcRotMiscVarTypeData%BlMB,1)
- i2_l = LBOUND(SrcRotMiscVarTypeData%BlMB,2)
- i2_u = UBOUND(SrcRotMiscVarTypeData%BlMB,2)
- i3_l = LBOUND(SrcRotMiscVarTypeData%BlMB,3)
- i3_u = UBOUND(SrcRotMiscVarTypeData%BlMB,3)
- IF (.NOT. ALLOCATED(DstRotMiscVarTypeData%BlMB)) THEN
- ALLOCATE(DstRotMiscVarTypeData%BlMB(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2)
- IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating DstRotMiscVarTypeData%BlMB.', ErrStat, ErrMsg,RoutineName)
- RETURN
- END IF
- END IF
- DstRotMiscVarTypeData%BlMB = SrcRotMiscVarTypeData%BlMB
-ENDIF
IF (ALLOCATED(SrcRotMiscVarTypeData%TwrFB)) THEN
i1_l = LBOUND(SrcRotMiscVarTypeData%TwrFB,1)
i1_u = UBOUND(SrcRotMiscVarTypeData%TwrFB,1)
@@ -9395,6 +9397,9 @@ SUBROUTINE AD_DestroyRotMiscVarType( RotMiscVarTypeData, ErrStat, ErrMsg, DEALLO
IF (ALLOCATED(RotMiscVarTypeData%orientationAnnulus)) THEN
DEALLOCATE(RotMiscVarTypeData%orientationAnnulus)
ENDIF
+IF (ALLOCATED(RotMiscVarTypeData%R_li)) THEN
+ DEALLOCATE(RotMiscVarTypeData%R_li)
+ENDIF
IF (ALLOCATED(RotMiscVarTypeData%AllOuts)) THEN
DEALLOCATE(RotMiscVarTypeData%AllOuts)
ENDIF
@@ -9434,6 +9439,9 @@ SUBROUTINE AD_DestroyRotMiscVarType( RotMiscVarTypeData, ErrStat, ErrMsg, DEALLO
IF (ALLOCATED(RotMiscVarTypeData%Mz)) THEN
DEALLOCATE(RotMiscVarTypeData%Mz)
ENDIF
+IF (ALLOCATED(RotMiscVarTypeData%Vind_i)) THEN
+ DEALLOCATE(RotMiscVarTypeData%Vind_i)
+ENDIF
IF (ALLOCATED(RotMiscVarTypeData%hub_theta_x_root)) THEN
DEALLOCATE(RotMiscVarTypeData%hub_theta_x_root)
ENDIF
@@ -9455,12 +9463,6 @@ SUBROUTINE AD_DestroyRotMiscVarType( RotMiscVarTypeData, ErrStat, ErrMsg, DEALLO
IF (ALLOCATED(RotMiscVarTypeData%CavitWarnSet)) THEN
DEALLOCATE(RotMiscVarTypeData%CavitWarnSet)
ENDIF
-IF (ALLOCATED(RotMiscVarTypeData%BlFB)) THEN
- DEALLOCATE(RotMiscVarTypeData%BlFB)
-ENDIF
-IF (ALLOCATED(RotMiscVarTypeData%BlMB)) THEN
- DEALLOCATE(RotMiscVarTypeData%BlMB)
-ENDIF
IF (ALLOCATED(RotMiscVarTypeData%TwrFB)) THEN
DEALLOCATE(RotMiscVarTypeData%TwrFB)
ENDIF
@@ -9672,6 +9674,11 @@ SUBROUTINE AD_PackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
Int_BufSz = Int_BufSz + 2*4 ! orientationAnnulus upper/lower bounds for each dimension
Db_BufSz = Db_BufSz + SIZE(InData%orientationAnnulus) ! orientationAnnulus
END IF
+ Int_BufSz = Int_BufSz + 1 ! R_li allocated yes/no
+ IF ( ALLOCATED(InData%R_li) ) THEN
+ Int_BufSz = Int_BufSz + 2*4 ! R_li upper/lower bounds for each dimension
+ Db_BufSz = Db_BufSz + SIZE(InData%R_li) ! R_li
+ END IF
Int_BufSz = Int_BufSz + 1 ! AllOuts allocated yes/no
IF ( ALLOCATED(InData%AllOuts) ) THEN
Int_BufSz = Int_BufSz + 2*1 ! AllOuts upper/lower bounds for each dimension
@@ -9736,6 +9743,11 @@ SUBROUTINE AD_PackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
IF ( ALLOCATED(InData%Mz) ) THEN
Int_BufSz = Int_BufSz + 2*2 ! Mz upper/lower bounds for each dimension
Re_BufSz = Re_BufSz + SIZE(InData%Mz) ! Mz
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! Vind_i allocated yes/no
+ IF ( ALLOCATED(InData%Vind_i) ) THEN
+ Int_BufSz = Int_BufSz + 2*3 ! Vind_i upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%Vind_i) ! Vind_i
END IF
Re_BufSz = Re_BufSz + SIZE(InData%V_DiskAvg) ! V_DiskAvg
Re_BufSz = Re_BufSz + 1 ! yaw
@@ -9801,16 +9813,6 @@ SUBROUTINE AD_PackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
Int_BufSz = Int_BufSz + 2*2 ! CavitWarnSet upper/lower bounds for each dimension
Int_BufSz = Int_BufSz + SIZE(InData%CavitWarnSet) ! CavitWarnSet
END IF
- Int_BufSz = Int_BufSz + 1 ! BlFB allocated yes/no
- IF ( ALLOCATED(InData%BlFB) ) THEN
- Int_BufSz = Int_BufSz + 2*3 ! BlFB upper/lower bounds for each dimension
- Re_BufSz = Re_BufSz + SIZE(InData%BlFB) ! BlFB
- END IF
- Int_BufSz = Int_BufSz + 1 ! BlMB allocated yes/no
- IF ( ALLOCATED(InData%BlMB) ) THEN
- Int_BufSz = Int_BufSz + 2*3 ! BlMB upper/lower bounds for each dimension
- Re_BufSz = Re_BufSz + SIZE(InData%BlMB) ! BlMB
- END IF
Int_BufSz = Int_BufSz + 1 ! TwrFB allocated yes/no
IF ( ALLOCATED(InData%TwrFB) ) THEN
Int_BufSz = Int_BufSz + 2*2 ! TwrFB upper/lower bounds for each dimension
@@ -10271,6 +10273,36 @@ SUBROUTINE AD_PackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
END DO
END DO
END IF
+ IF ( .NOT. ALLOCATED(InData%R_li) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%R_li,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%R_li,1)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%R_li,2)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%R_li,2)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%R_li,3)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%R_li,3)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%R_li,4)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%R_li,4)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i4 = LBOUND(InData%R_li,4), UBOUND(InData%R_li,4)
+ DO i3 = LBOUND(InData%R_li,3), UBOUND(InData%R_li,3)
+ DO i2 = LBOUND(InData%R_li,2), UBOUND(InData%R_li,2)
+ DO i1 = LBOUND(InData%R_li,1), UBOUND(InData%R_li,1)
+ DbKiBuf(Db_Xferred) = InData%R_li(i1,i2,i3,i4)
+ Db_Xferred = Db_Xferred + 1
+ END DO
+ END DO
+ END DO
+ END DO
+ END IF
IF ( .NOT. ALLOCATED(InData%AllOuts) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
@@ -10510,6 +10542,31 @@ SUBROUTINE AD_PackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
Re_Xferred = Re_Xferred + 1
END DO
END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%Vind_i) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_i,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_i,1)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_i,2)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_i,2)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%Vind_i,3)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Vind_i,3)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i3 = LBOUND(InData%Vind_i,3), UBOUND(InData%Vind_i,3)
+ DO i2 = LBOUND(InData%Vind_i,2), UBOUND(InData%Vind_i,2)
+ DO i1 = LBOUND(InData%Vind_i,1), UBOUND(InData%Vind_i,1)
+ ReKiBuf(Re_Xferred) = InData%Vind_i(i1,i2,i3)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END DO
END IF
DO i1 = LBOUND(InData%V_DiskAvg,1), UBOUND(InData%V_DiskAvg,1)
ReKiBuf(Re_Xferred) = InData%V_DiskAvg(i1)
@@ -10665,56 +10722,6 @@ SUBROUTINE AD_PackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
END DO
END DO
END IF
- IF ( .NOT. ALLOCATED(InData%BlFB) ) THEN
- IntKiBuf( Int_Xferred ) = 0
- Int_Xferred = Int_Xferred + 1
- ELSE
- IntKiBuf( Int_Xferred ) = 1
- Int_Xferred = Int_Xferred + 1
- IntKiBuf( Int_Xferred ) = LBOUND(InData%BlFB,1)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlFB,1)
- Int_Xferred = Int_Xferred + 2
- IntKiBuf( Int_Xferred ) = LBOUND(InData%BlFB,2)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlFB,2)
- Int_Xferred = Int_Xferred + 2
- IntKiBuf( Int_Xferred ) = LBOUND(InData%BlFB,3)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlFB,3)
- Int_Xferred = Int_Xferred + 2
-
- DO i3 = LBOUND(InData%BlFB,3), UBOUND(InData%BlFB,3)
- DO i2 = LBOUND(InData%BlFB,2), UBOUND(InData%BlFB,2)
- DO i1 = LBOUND(InData%BlFB,1), UBOUND(InData%BlFB,1)
- ReKiBuf(Re_Xferred) = InData%BlFB(i1,i2,i3)
- Re_Xferred = Re_Xferred + 1
- END DO
- END DO
- END DO
- END IF
- IF ( .NOT. ALLOCATED(InData%BlMB) ) THEN
- IntKiBuf( Int_Xferred ) = 0
- Int_Xferred = Int_Xferred + 1
- ELSE
- IntKiBuf( Int_Xferred ) = 1
- Int_Xferred = Int_Xferred + 1
- IntKiBuf( Int_Xferred ) = LBOUND(InData%BlMB,1)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlMB,1)
- Int_Xferred = Int_Xferred + 2
- IntKiBuf( Int_Xferred ) = LBOUND(InData%BlMB,2)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlMB,2)
- Int_Xferred = Int_Xferred + 2
- IntKiBuf( Int_Xferred ) = LBOUND(InData%BlMB,3)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%BlMB,3)
- Int_Xferred = Int_Xferred + 2
-
- DO i3 = LBOUND(InData%BlMB,3), UBOUND(InData%BlMB,3)
- DO i2 = LBOUND(InData%BlMB,2), UBOUND(InData%BlMB,2)
- DO i1 = LBOUND(InData%BlMB,1), UBOUND(InData%BlMB,1)
- ReKiBuf(Re_Xferred) = InData%BlMB(i1,i2,i3)
- Re_Xferred = Re_Xferred + 1
- END DO
- END DO
- END DO
- END IF
IF ( .NOT. ALLOCATED(InData%TwrFB) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
@@ -11481,6 +11488,39 @@ SUBROUTINE AD_UnPackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat
END DO
END DO
END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! R_li not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i2_l = IntKiBuf( Int_Xferred )
+ i2_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i3_l = IntKiBuf( Int_Xferred )
+ i3_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i4_l = IntKiBuf( Int_Xferred )
+ i4_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%R_li)) DEALLOCATE(OutData%R_li)
+ ALLOCATE(OutData%R_li(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u,i4_l:i4_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%R_li.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i4 = LBOUND(OutData%R_li,4), UBOUND(OutData%R_li,4)
+ DO i3 = LBOUND(OutData%R_li,3), UBOUND(OutData%R_li,3)
+ DO i2 = LBOUND(OutData%R_li,2), UBOUND(OutData%R_li,2)
+ DO i1 = LBOUND(OutData%R_li,1), UBOUND(OutData%R_li,1)
+ OutData%R_li(i1,i2,i3,i4) = REAL(DbKiBuf(Db_Xferred), R8Ki)
+ Db_Xferred = Db_Xferred + 1
+ END DO
+ END DO
+ END DO
+ END DO
+ END IF
IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! AllOuts not allocated
Int_Xferred = Int_Xferred + 1
ELSE
@@ -11759,6 +11799,34 @@ SUBROUTINE AD_UnPackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat
Re_Xferred = Re_Xferred + 1
END DO
END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Vind_i not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i2_l = IntKiBuf( Int_Xferred )
+ i2_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i3_l = IntKiBuf( Int_Xferred )
+ i3_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%Vind_i)) DEALLOCATE(OutData%Vind_i)
+ ALLOCATE(OutData%Vind_i(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Vind_i.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i3 = LBOUND(OutData%Vind_i,3), UBOUND(OutData%Vind_i,3)
+ DO i2 = LBOUND(OutData%Vind_i,2), UBOUND(OutData%Vind_i,2)
+ DO i1 = LBOUND(OutData%Vind_i,1), UBOUND(OutData%Vind_i,1)
+ OutData%Vind_i(i1,i2,i3) = ReKiBuf(Re_Xferred)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END DO
END IF
i1_l = LBOUND(OutData%V_DiskAvg,1)
i1_u = UBOUND(OutData%V_DiskAvg,1)
@@ -11955,62 +12023,6 @@ SUBROUTINE AD_UnPackRotMiscVarType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat
END DO
END DO
END IF
- IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlFB not allocated
- Int_Xferred = Int_Xferred + 1
- ELSE
- Int_Xferred = Int_Xferred + 1
- i1_l = IntKiBuf( Int_Xferred )
- i1_u = IntKiBuf( Int_Xferred + 1)
- Int_Xferred = Int_Xferred + 2
- i2_l = IntKiBuf( Int_Xferred )
- i2_u = IntKiBuf( Int_Xferred + 1)
- Int_Xferred = Int_Xferred + 2
- i3_l = IntKiBuf( Int_Xferred )
- i3_u = IntKiBuf( Int_Xferred + 1)
- Int_Xferred = Int_Xferred + 2
- IF (ALLOCATED(OutData%BlFB)) DEALLOCATE(OutData%BlFB)
- ALLOCATE(OutData%BlFB(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2)
- IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlFB.', ErrStat, ErrMsg,RoutineName)
- RETURN
- END IF
- DO i3 = LBOUND(OutData%BlFB,3), UBOUND(OutData%BlFB,3)
- DO i2 = LBOUND(OutData%BlFB,2), UBOUND(OutData%BlFB,2)
- DO i1 = LBOUND(OutData%BlFB,1), UBOUND(OutData%BlFB,1)
- OutData%BlFB(i1,i2,i3) = ReKiBuf(Re_Xferred)
- Re_Xferred = Re_Xferred + 1
- END DO
- END DO
- END DO
- END IF
- IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! BlMB not allocated
- Int_Xferred = Int_Xferred + 1
- ELSE
- Int_Xferred = Int_Xferred + 1
- i1_l = IntKiBuf( Int_Xferred )
- i1_u = IntKiBuf( Int_Xferred + 1)
- Int_Xferred = Int_Xferred + 2
- i2_l = IntKiBuf( Int_Xferred )
- i2_u = IntKiBuf( Int_Xferred + 1)
- Int_Xferred = Int_Xferred + 2
- i3_l = IntKiBuf( Int_Xferred )
- i3_u = IntKiBuf( Int_Xferred + 1)
- Int_Xferred = Int_Xferred + 2
- IF (ALLOCATED(OutData%BlMB)) DEALLOCATE(OutData%BlMB)
- ALLOCATE(OutData%BlMB(i1_l:i1_u,i2_l:i2_u,i3_l:i3_u),STAT=ErrStat2)
- IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%BlMB.', ErrStat, ErrMsg,RoutineName)
- RETURN
- END IF
- DO i3 = LBOUND(OutData%BlMB,3), UBOUND(OutData%BlMB,3)
- DO i2 = LBOUND(OutData%BlMB,2), UBOUND(OutData%BlMB,2)
- DO i1 = LBOUND(OutData%BlMB,1), UBOUND(OutData%BlMB,1)
- OutData%BlMB(i1,i2,i3) = ReKiBuf(Re_Xferred)
- Re_Xferred = Re_Xferred + 1
- END DO
- END DO
- END DO
- END IF
IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! TwrFB not allocated
Int_Xferred = Int_Xferred + 1
ELSE
diff --git a/modules/aerodyn/src/BEMT.f90 b/modules/aerodyn/src/BEMT.f90
index d62b855be5..33fe5d2821 100644
--- a/modules/aerodyn/src/BEMT.f90
+++ b/modules/aerodyn/src/BEMT.f90
@@ -348,12 +348,12 @@ subroutine BEMT_AllocInput( u, p, errStat, errMsg )
end if
u%theta = 0.0_ReKi
- allocate ( u%psi( p%numBlades ), STAT = errStat2 )
+ allocate ( u%psi_s( p%numBlades ), STAT = errStat2 )
if ( errStat2 /= 0 ) then
- call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%psi.', errStat, errMsg, RoutineName )
+ call SetErrStat( ErrID_Fatal, 'Error allocating memory for u%psi_s.', errStat, errMsg, RoutineName )
return
end if
- u%psi = 0.0_ReKi
+ u%psi_s = 0.0_ReKi
allocate ( u%Vx( p%numBladeNodes, p%numBlades ), STAT = errStat2 )
if ( errStat2 /= 0 ) then
@@ -459,6 +459,11 @@ subroutine BEMT_AllocOutput( y, p, errStat, errMsg )
call allocAry( y%Re, p%numBladeNodes, p%numBlades, 'y%Re', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
call allocAry( y%axInduction, p%numBladeNodes, p%numBlades, 'y%axInduction', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
call allocAry( y%tanInduction, p%numBladeNodes, p%numBlades, 'y%tanInduction', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
+ call allocAry( y%axInduction_qs, p%numBladeNodes, p%numBlades, 'y%axInduction_qs', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
+ call allocAry( y%tanInduction_qs, p%numBladeNodes, p%numBlades, 'y%tanInduction_qs', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
+ call allocAry( y%F, p%numBladeNodes, p%numBlades, 'y%F', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
+ call allocAry( y%k, p%numBladeNodes, p%numBlades, 'y%k', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
+ call allocAry( y%k_p, p%numBladeNodes, p%numBlades, 'y%k_p', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
call allocAry( y%AOA, p%numBladeNodes, p%numBlades, 'y%AOA', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
call allocAry( y%Cx, p%numBladeNodes, p%numBlades, 'y%Cx', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
call allocAry( y%Cy, p%numBladeNodes, p%numBlades, 'y%Cy', errStat2, errMsg2); call setErrStat(errStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
@@ -489,6 +494,11 @@ subroutine BEMT_AllocOutput( y, p, errStat, errMsg )
y%Re = 0.0_ReKi
y%axInduction = 0.0_ReKi
y%tanInduction = 0.0_ReKi
+ y%axInduction_qs = 0.0_ReKi
+ y%tanInduction_qs = 0.0_ReKi
+ y%F = 0.0_ReKi
+ y%k = 0.0_ReKi
+ y%k_p = 0.0_ReKi
y%AOA = 0.0_ReKi
y%Cl = 0.0_ReKi
y%Cd = 0.0_ReKi
@@ -1059,7 +1069,7 @@ subroutine GetRTip( u, p, RTip )
end subroutine GetRTip
!..................................................................................................................................
-subroutine calculate_Inductions_from_BEMT(p,phi,u,OtherState,AFInfo,axInduction,tanInduction, ErrStat,ErrMsg)
+subroutine calculate_Inductions_from_BEMT(p,phi,u,OtherState,AFInfo,axInduction,tanInduction, ErrStat,ErrMsg, k_out, kp_out, F_out)
type(BEMT_ParameterType), intent(in ) :: p !< Parameters
real(ReKi), intent(in ) :: phi(:,:) !< phi
@@ -1070,6 +1080,9 @@ subroutine calculate_Inductions_from_BEMT(p,phi,u,OtherState,AFInfo,axInduction,
real(ReKi), intent(inout) :: tanInduction(:,:) !< tangential induction
integer(IntKi), intent( out) :: errStat !< Error status of the operation
character(*), intent( out) :: errMsg !< Error message if ErrStat /= ErrID_None
+ real(ReKi), optional, intent(inout) :: k_out(:,:) !<
+ real(ReKi), optional, intent(inout) :: kp_out(:,:) !<
+ real(ReKi), optional, intent(inout) :: F_out(:,:) !< hub/tip loss factor
integer(IntKi) :: i !< blade node counter
integer(IntKi) :: j !< blade counter
@@ -1079,6 +1092,7 @@ subroutine calculate_Inductions_from_BEMT(p,phi,u,OtherState,AFInfo,axInduction,
integer(IntKi) :: errStat2 !< Error status of the operation
character(ErrMsgLen) :: errMsg2 !< Error message if ErrStat /= ErrID_None
character(*), parameter :: RoutineName = 'calculate_Inductions_from_BEMT'
+ real(ReKi) :: kp, k, F !< Optional variables returned by BEM
ErrStat = ErrID_None
ErrMsg = ""
@@ -1091,7 +1105,10 @@ subroutine calculate_Inductions_from_BEMT(p,phi,u,OtherState,AFInfo,axInduction,
! Need to get the induction factors for these conditions without skewed wake correction and without UA
! COMPUTE: axInduction, tanInduction
- fzero = BEMTU_InductionWithResidual(p, u, i, j, phi(i,j), AFInfo(p%AFIndx(i,j)), IsValidSolution, ErrStat2, ErrMsg2, a=axInduction(i,j), ap=tanInduction(i,j))
+ fzero = BEMTU_InductionWithResidual(p, u, i, j, phi(i,j), AFInfo(p%AFIndx(i,j)), IsValidSolution, ErrStat2, ErrMsg2, a=axInduction(i,j), ap=tanInduction(i,j), kp_out=kp, k_out=k, F_out=F)
+ if (present(kp_out)) kp_out(i,j) = kp
+ if (present(k_out)) k_out(i,j) = k
+ if (present(F_out)) F_out(i,j) = F
if (ErrStat2 /= ErrID_None) then
call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName//trim(NodeText(i,j)))
@@ -1383,7 +1400,8 @@ subroutine BEMT_InitStates(t, u, p, x, xd, z, OtherState, m, AFInfo, ErrStat, Er
end subroutine BEMT_InitStates
!----------------------------------------------------------------------------------------------------------------------------------
!> Routine for computing inductions outputs, used in both loose and tight coupling.
-subroutine BEMT_CalcOutput_Inductions( InputIndex, t, CalculateDBEMTInputs, ApplyCorrections, phi, u, p, x, xd, z, OtherState, AFInfo, axInduction, tanInduction, chi, m, errStat, errMsg )
+subroutine BEMT_CalcOutput_Inductions( InputIndex, t, CalculateDBEMTInputs, ApplyCorrections, phi, u, p, x, xd, z, OtherState, AFInfo, axInduction, tanInduction, chi, m, errStat, errMsg, &
+ axInduction_qs_out, tanInduction_qs_out, k_out, kp_out, F_out)
!..................................................................................................................................
REAL(DbKi), intent(in ) :: t ! current simulation time
@@ -1404,6 +1422,11 @@ subroutine BEMT_CalcOutput_Inductions( InputIndex, t, CalculateDBEMTInputs, Appl
REAL(ReKi), intent(inout) :: chi(:,:) ! value used in skewed wake correction
integer(IntKi), intent( out) :: errStat ! Error status of the operation
character(*), intent( out) :: errMsg ! Error message if ErrStat /= ErrID_None
+ REAL(ReKi), optional, intent( out) :: axInduction_qs_out(:,:) !Quasi steady axial induction.
+ REAL(ReKi), optional, intent( out) :: tanInduction_qs_out(:,:)
+ REAL(ReKi), optional, intent( out) :: k_out(:,:) ! NOTE: if provided, kp_out and F_out should be provided
+ REAL(ReKi), optional, intent( out) :: kp_out(:,:)
+ REAL(ReKi), optional, intent( out) :: F_out(:,:)
! Local variables:
@@ -1452,9 +1475,17 @@ subroutine BEMT_CalcOutput_Inductions( InputIndex, t, CalculateDBEMTInputs, Appl
!............................................
! get BEMT inductions (axInduction and tanInduction):
!............................................
- call calculate_Inductions_from_BEMT(p, phi, u, OtherState, AFInfo, axInduction, tanInduction, ErrStat2, ErrMsg2)
- call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
- if (errStat >= AbortErrLev) return
+ ! NOTE: we assume that all optional arguments (k/kp/F) are provided or none at all.
+ if (present(k_out)) then
+ call calculate_Inductions_from_BEMT(p, phi, u, OtherState, AFInfo, axInduction, tanInduction, ErrStat2, ErrMsg2, k_out, kp_out, F_out)
+ else
+ call calculate_Inductions_from_BEMT(p, phi, u, OtherState, AFInfo, axInduction, tanInduction, ErrStat2, ErrMsg2)
+ endif
+ call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
+ if (errStat >= AbortErrLev) return
+ ! Backup optional variables
+ if (present(axInduction_qs_out)) axInduction_qs_out = axInduction
+ if (present(tanInduction_qs_out)) tanInduction_qs_out = tanInduction
!............................................
! apply DBEMT correction to axInduction and tanInduction:
@@ -1554,7 +1585,7 @@ subroutine ApplySkewedWakeCorrection_AllNodes(p, u, m, x, phi, OtherState, axInd
do i = 1,p%numBladeNodes ! Loop through the blade nodes / elements
if ( .not. p%FixedInductions(i,j) ) then
F = getHubTipLossCorrection(p%BEM_Mod, p%useHubLoss, p%useTipLoss, p%hubLossConst(i,j), p%tipLossConst(i,j), phi(i,j), u%cantAngle(i,j) )
- call ApplySkewedWakeCorrection( p%BEM_Mod, p%skewWakeMod, p%yawCorrFactor, F, u%psi(j), u%psiSkewOffset, u%chi0, u%rlocal(i,j)/m%Rtip(j), axInduction(i,j), chi(i,j), m%FirstWarn_Skew )
+ call ApplySkewedWakeCorrection( p%BEM_Mod, p%skewWakeMod, p%yawCorrFactor, F, u%psi_s(j), u%psiSkewOffset, u%chi0, u%rlocal(i,j)/m%Rtip(j), axInduction(i,j), chi(i,j), m%FirstWarn_Skew )
end if ! .not. p%FixedInductions (special case for tip and/or hub loss)
enddo ! I - Blade nodes / elements
enddo ! J - All blades
@@ -2395,7 +2426,7 @@ subroutine WriteDEBUGValuesToFile(t, u, p, x, xd, z, OtherState, m, AFInfo)
, z%phi( DEBUG_BLADENODE,DEBUG_BLADE)*R2D & ! remember this does not have any corrections
, u%chi0, u%omega, u%Un_disk, u%TSR &
, u%theta( DEBUG_BLADENODE,DEBUG_BLADE) &
- , u%psi( DEBUG_BLADE) &
+ , u%psi_s( DEBUG_BLADE) &
, u%Vx( DEBUG_BLADENODE,DEBUG_BLADE) &
, u%Vy( DEBUG_BLADENODE,DEBUG_BLADE) &
, u%Vz( DEBUG_BLADENODE,DEBUG_BLADE) &
diff --git a/modules/aerodyn/src/BEMTUncoupled.f90 b/modules/aerodyn/src/BEMTUncoupled.f90
index 5d4b9a34fe..e8f65c6961 100644
--- a/modules/aerodyn/src/BEMTUncoupled.f90
+++ b/modules/aerodyn/src/BEMTUncoupled.f90
@@ -63,15 +63,9 @@ module BEMTUnCoupled
!..................................................................................................................................
function VelocityIsZero ( v )
-
- ! passed variables
-
REAL(ReKi), INTENT(IN ) :: v !< the velocity that needs to be compared with zero
-
LOGICAL :: VelocityIsZero !< .true. if and only if the velocity is (almost) equal to zero
-
-
-
+
VelocityIsZero = abs(v) < 0.001_ReKi ! tolerance in m/s for what we consider zero velocity for BEM computations
end function VelocityIsZero
@@ -135,7 +129,7 @@ subroutine GetRelativeVelocity( axInduction, tanInduction, Vx, Vy, cantAngle, xV
end subroutine GetRelativeVelocity
!..................................................................................................................................
-!> getAirfoilOrientation = R_ap = transformation from from polar coordinate system of the section to the airfoil coordinate system
+!> getAirfoilOrientation = R_al = transformation from from local-polar coordinate system of the section to the airfoil coordinate system
subroutine getAirfoilOrientation( theta, cantAngle, toeAngle, afAxialVec, afNormalVec, afRadialVec )
! Routine for creating the airfoil orientation vectors
@@ -153,7 +147,7 @@ subroutine getAirfoilOrientation( theta, cantAngle, toeAngle, afAxialVec, afNorm
orientation(1) = toeAngle
orientation(2) = cantAngle
orientation(3) = -theta
- rotMat = EulerConstruct( orientation ) ! = R_ap: from polar to airfoil
+ rotMat = EulerConstruct( orientation ) ! = R_al: from local-polar to airfoil
! unit vector normal to the chord line in the airfoil plane
afNormalVec = rotMat(1,:)
@@ -167,7 +161,7 @@ subroutine getAirfoilOrientation( theta, cantAngle, toeAngle, afAxialVec, afNorm
end subroutine getAirfoilOrientation
!..................................................................................................................................
-!> getAirfoilOrientation = R_ap = transformation from from polar coordinate system of the section to the airfoil coordinate system
+!> getAirfoilOrientation = R_al = transformation from from local-polar coordinate system of the section to the airfoil coordinate system
subroutine getAirfoilOrientationMatrix( theta, cantAngle, toeAngle, rotMat)
! Routine for creating the airfoil orientation vectors
@@ -182,7 +176,7 @@ subroutine getAirfoilOrientationMatrix( theta, cantAngle, toeAngle, rotMat)
orientation(1) = toeAngle
orientation(2) = cantAngle
orientation(3) = -theta
- rotMat = EulerConstruct( orientation ) ! = R_ap: from polar to airfoil
+ rotMat = EulerConstruct( orientation ) ! = R_al: from local-polar to airfoil
end subroutine getAirfoilOrientationMatrix
!..................................................................................................................................
subroutine computeAirfoilOperatingAOA( BEM_Mod, phi, theta, cantAngle, toeAngle, AoA )
@@ -234,6 +228,9 @@ subroutine computeAirfoilOperatingAOA( BEM_Mod, phi, theta, cantAngle, toeAngle,
end subroutine computeAirfoilOperatingAOA
!..................................................................................................................................
+!> Transform the aerodynamic coefficients (Cl,Cd,Cm) (directed based on Vrel_xy_a )
+!! from the airfoil coordinate system (a) to the without sweep pitch coordinate system (w)
+!! NOTE: "Cy" is currently "-Cyw"
subroutine Transform_ClCd_to_CxCy( phi, useAIDrag, useTIDrag, Cl, Cd, Cx, Cy )
real(ReKi), intent(in ) :: phi
logical, intent(in ) :: useAIDrag
@@ -249,12 +246,14 @@ subroutine Transform_ClCd_to_CxCy( phi, useAIDrag, useTIDrag, Cl, Cd, Cx, Cy )
sphi = sin(phi)
! resolve into normal (x) and tangential (y) forces
+ ! Cx = Cxw
if ( useAIDrag ) then
Cx = Cl*cphi + Cd*sphi
else
Cx = Cl*cphi
end if
+ ! Cy = -Cyw
if ( useTIDrag ) then
Cy = Cl*sphi - Cd*cphi
else
@@ -263,6 +262,9 @@ subroutine Transform_ClCd_to_CxCy( phi, useAIDrag, useTIDrag, Cl, Cd, Cx, Cy )
end subroutine Transform_ClCd_to_CxCy
!----------------------------------------------------------------------------------------------------------------------------------
+!> Transform the aerodynamic coefficients (Cl,Cd,Cm) (directed based on Vrel_xy_a )
+!! from the airfoil coordinate system (a) to the local-polar coordinate system (l)
+!! NOTE: "Cy" is currently "-Cyl"
subroutine Transform_ClCdCm_to_CxCyCzCmxCmyCmz( phi, theta, cant,toeAngle ,useAIDrag, useTIDrag, AOA, Cl, Cd, Cm, Cx, Cy, Cz, Cmx, Cmy, Cmz )
implicit none
@@ -279,9 +281,9 @@ subroutine Transform_ClCdCm_to_CxCyCzCmxCmyCmz( phi, theta, cant,toeAngle ,useAI
real(ReKi), intent(in ) :: Cm
real(ReKi), intent( out) :: Cx, Cy, Cz
real(ReKi), intent( out) :: Cmx, Cmy, Cmz
- real(ReKi) :: afAxialVec(3)
- real(ReKi) :: afNormalVec(3)
- real(ReKi) :: afRadialVec(3)
+ real(ReKi) :: afAxialVec(3) !xhat_a_in_l
+ real(ReKi) :: afNormalVec(3) !yhat_a_in_l
+ real(ReKi) :: afRadialVec(3) !zhat_a_in_l
real(ReKi) :: coeffVec(3)
real(ReKi) :: Cn
real(ReKi) :: Ct
@@ -290,11 +292,13 @@ subroutine Transform_ClCdCm_to_CxCyCzCmxCmyCmz( phi, theta, cant,toeAngle ,useAI
call getAirfoilOrientation( theta, cant, toeAngle, afAxialVec, afNormalVec, afRadialVec )
! transform force coefficients into airfoil frame
+ ! Cn = Cxa
if ( useAIDrag ) then
Cn = Cl*cos(AOA) + Cd*sin(AOA)
else
Cn = Cl*cos(AOA)
end if
+ ! Ct = Cya
if ( useTIDrag ) then
Ct = -Cl*sin(AOA) + Cd*cos(AOA)
else
@@ -303,9 +307,9 @@ subroutine Transform_ClCdCm_to_CxCyCzCmxCmyCmz( phi, theta, cant,toeAngle ,useAI
! Put force coefficients back into rotor plane reference frame
coeffVec = Cn*afNormalVec + Ct*afAxialVec
- Cx = coeffVec(1)
- Cy = -coeffVec(2)
- Cz = coeffVec(3)
+ Cx = coeffVec(1) ! Cxl and cn
+ Cy = -coeffVec(2) ! -Cyl ct
+ Cz = coeffVec(3) ! Czl
! Put moment coefficients into the rotor reference frame
coeffVec = Cm * afRadialVec
@@ -315,7 +319,7 @@ subroutine Transform_ClCdCm_to_CxCyCzCmxCmyCmz( phi, theta, cant,toeAngle ,useAI
end subroutine Transform_ClCdCm_to_CxCyCzCmxCmyCmz
!----------------------------------------------------------------------------------------------------------------------------------
!>This is the residual calculation for the uncoupled BEM solve
-real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValidSolution, ErrStat, ErrMsg, a, ap, k, kp, Cx_out, Cy_out ) result (ResidualVal)
+real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValidSolution, ErrStat, ErrMsg, a, ap, k_out, kp_out, F_out, Cx_out, Cy_out ) result (ResidualVal)
type(BEMT_ParameterType),intent(in ) :: p !< parameters
@@ -330,8 +334,10 @@ real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValid
character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None
real(ReKi), optional, intent( out) :: a ! computed axial induction
real(ReKi), optional, intent( out) :: ap ! computed tangential induction
- real(ReKi), optional, intent( out) :: k ! k in the induction factors routine
- real(ReKi), optional, intent( out) :: kp ! kp in the induction factors routine
+ real(ReKi), optional, intent( out) :: k_out ! k in the induction factors routine
+ real(ReKi), optional, intent( out) :: kp_out ! kp in the induction factors routine
+ real(ReKi), optional, intent( out) :: F_out ! Tip/hub loss factor
+ real(ReKi), optional, intent( out) :: Cx_out, Cy_out !< cn and ct
! Local variables
@@ -344,11 +350,12 @@ real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValid
real(ReKi) :: axInduction
real(ReKi) :: tanInduction
- real(ReKi) :: F ! tip/hub loss factor
+ real(ReKi) :: F !< tip/hub loss factor
real(ReKi) :: Re
- real(ReKi) :: Cx, Cy, Cz
- real(ReKi), optional, intent( out) :: Cx_out, Cy_out
- real(ReKi) :: dumX,dumY,dumZ, k_out, kp_out
+ real(ReKi) :: Cx !< Projected airfoil coefficient used in BET, cn
+ real(ReKi) :: Cy !< Projected airfoil coefficient used in BET, ct
+ real(ReKi) :: Cz
+ real(ReKi) :: dumX,dumY,dumZ, k, kp
TYPE(AFI_OutputType) :: AFI_interp
ErrStat = ErrID_None
@@ -356,8 +363,12 @@ real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValid
ResidualVal = 0.0_ReKi
IsValidSolution = .true.
- k_out = 0
- kp_out = 0
+ ! Optional outputs
+ F = 1._ReKi
+ k = 0._ReKi
+ kp = 0._ReKi
+ Cx = 0._ReKi
+ Cy = 0._ReKi
! make these return values consistent with what is returned in inductionFactors routine:
! Set the local version of the induction factors
@@ -382,6 +393,8 @@ real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValid
if (ErrStat >= AbortErrLev) return
! Compute Cx, Cy given Cl, Cd and phi, we honor the useAIDrag and useTIDrag flag because Cx,Cy are only used for the solution of inductions
+ ! BEMMod_2D: Cx = Cxw and Cy = - Cyw
+ ! BEMMod_3D: Cx = cn = Cxp and Cy = ct =-Cyp
if(p%BEM_Mod==BEMMod_2D) then
call Transform_ClCd_to_CxCy( phi, p%useAIDrag, p%useTIDrag, AFI_interp%Cl, AFI_interp%Cd, Cx, Cy )
else
@@ -401,10 +414,10 @@ real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValid
! Determine axInduction, tanInduction for the current Cl, Cd, phi
if(p%BEM_Mod==BEMMod_2D) then
call inductionFactors0(p%numBlades, u%rlocal(i,j), p%chord(i,j), phi, Cx, Cy, u%Vx(i,j), u%Vy(i,j), F, p%useTanInd, &
- ResidualVal, axInduction, tanInduction, IsValidSolution)
+ ResidualVal, axInduction, tanInduction, IsValidSolution, k, kp)
else
call inductionFactors2(p%BEM_Mod, p%numBlades, u%rlocal(i,j), p%chord(i,j), phi, Cx, Cy, u%Vx(i,j), u%Vy(i,j), u%drdz(i,j), u%cantAngle(i,j), F, u%CHI0, p%useTanInd, &
- ResidualVal, axInduction, tanInduction, p%MomentumCorr, u%xVelCorr(i,j), IsValidSolution, k_out, kp_out )
+ ResidualVal, axInduction, tanInduction, p%MomentumCorr, u%xVelCorr(i,j), IsValidSolution, k, kp )
endif
@@ -412,10 +425,11 @@ real(ReKi) function BEMTU_InductionWithResidual(p, u, i, j, phi, AFInfo, IsValid
if (present(a )) a = axInduction
if (present(ap)) ap = tanInduction
- if (present(k )) k = k_out
- if (present(kp)) kp = kp_out
+ if (present(k_out )) k_out = k
+ if (present(kp_out)) kp_out = kp
if (present(Cx_out)) Cx_out = Cx
if (present(Cy_out)) Cy_out = Cy
+ if (present(F_out)) F_out = F
end function BEMTU_InductionWithResidual
!-----------------------------------------------------------------------------------------
@@ -439,14 +453,12 @@ subroutine ApplySkewedWakeCorrection(BEM_Mod, SkewMod, yawCorrFactor, F, azimuth
! Skewed wake correction
- IF (.true.) then
- if(BEM_Mod==BEMMod_2D) then
- chi = (0.6_ReKi*a + 1.0_ReKi)*chi0
- else
- chi = (0.6_ReKi*a + 1.0_ReKi)*abs(chi0)
- endif
- END IF
-
+ if(BEM_Mod==BEMMod_2D) then
+ chi = (0.6_ReKi*a + 1.0_ReKi)*chi0
+ else
+ chi = (0.6_ReKi*a + 1.0_ReKi)*abs(chi0)
+ endif
+
call MPi2Pi( chi ) ! make sure chi is in [-pi, pi] before testing if it's outside a valid range
if (abs(chi) > piBy2) then
@@ -473,7 +485,7 @@ end subroutine ApplySkewedWakeCorrection
!-----------------------------------------------------------------------------------------
!> This subroutine computes the induction factors (a) and (ap) along with the residual (fzero)
subroutine inductionFactors0(B, r, chord, phi, cn, ct, Vx, Vy, F, wakerotation, &
- fzero, a_out, ap_out, IsValidSolution)
+ fzero, a_out, ap_out, IsValidSolution, k_out, kp_out)
implicit none
@@ -494,6 +506,8 @@ subroutine inductionFactors0(B, r, chord, phi, cn, ct, Vx, Vy, F, wakerotation,
real(ReKi), intent(out) :: a_out !< axial induction [y%axInduction]
real(ReKi), intent(out) :: ap_out !< tangential induction, i.e., a-prime [y%tanInduction]
logical, intent(out) :: IsValidSolution !< this is set to false if k<=1 in the propeller brake region or k<-1 in the momentum region, indicating an invalid solution
+ real(ReKi), intent(out) :: k_out
+ real(ReKi), intent(out) :: kp_out
! local
@@ -621,14 +635,14 @@ subroutine inductionFactors0(B, r, chord, phi, cn, ct, Vx, Vy, F, wakerotation,
ap_out = real( ap, ReKi )
end subroutine inductionFactors0
-subroutine getTangentialInduction(a, cphi, sphi, Vx, F, kCorrectionFactor, sigma_p, ct, VxCorrected, effectiveYaw, H, MomentumCorr, ap, kp)
+subroutine getTangentialInduction(a, cphi, sphi, Vx, F, kpCorrectionFactor, sigma_p, ct, VxCorrected, effectiveYaw, H, MomentumCorr, ap, kp)
real(ReKi), intent(in) :: Vx !< velocity component [u%Vx]
real(ReKi), intent(in) :: F !< hub/tip loss correction factor
logical, intent(in) :: MomentumCorr !< Include tangential induction in BEMT calculations [flag] [p%useTanInd]
real(ReKi), intent(in) :: ct !< tangential force coefficient (tangential to the plane, not chord) of the jth node in the kth blade; [y%cy]
real(R8Ki), intent(in) :: sigma_p ! local solidity (B*chord/(TwoPi*r))
real(R8Ki), intent(in) :: sphi, cphi ! sin(phi), cos(phi)
- real(R8Ki), intent(in) :: VxCorrected, kCorrectionFactor
+ real(R8Ki), intent(in) :: VxCorrected, kpCorrectionFactor
real(R8Ki), intent(in) :: effectiveYaw !
real(R8Ki), intent(in) :: H ! scaling factor to gradually phase out tangential induction when axial induction is near 1.0
real(R8Ki), intent(in) :: a ! double precision versions of output variables of similar name
@@ -644,15 +658,15 @@ subroutine getTangentialInduction(a, cphi, sphi, Vx, F, kCorrectionFactor, sigma
else
!H = smoothStep( real(a,ReKi), 0.8, 1.0, 1.0, 0.0 ) + smoothStep( real(a,ReKi), 1.0, 0.0, 1.2, 1.0 )
- !kp = sigma_p*( cl*sphi - H*cd*cphi )/( 4.0*F*sphi*cphi )*kCorrectionFactor
+ !kp = sigma_p*( cl*sphi - H*cd*cphi )/( 4.0*F*sphi*cphi )*kpCorrectionFactor
if (MomentumCorr) then
if (equalrealnos(a,1.0_R8Ki)) then
- kp = 0.0_R8Ki !H*sigma_p*ct/( 4.0*F*sphi*cphi )*(kCorrectionFactor)
+ kp = 0.0_R8Ki !H*sigma_p*ct/( 4.0*F*sphi*cphi )*(kpCorrectionFactor)
else
- kp = H*sigma_p*ct/( 4.0*F*sphi*cphi )*(kCorrectionFactor)/sqrt(1+(tan(effectiveYaw)/(1.0_ReKi-a))**2)
+ kp = H*sigma_p*ct/( 4.0*F*sphi*cphi )*(kpCorrectionFactor)/sqrt(1+(tan(effectiveYaw)/(1.0_ReKi-a))**2)
endif
else
- kp = H*sigma_p*ct/( 4.0*F*sphi*cphi )*kCorrectionFactor
+ kp = H*sigma_p*ct/( 4.0*F*sphi*cphi )*kpCorrectionFactor
endif
if ( VxCorrected < 0.0_ReKi ) then
@@ -705,11 +719,12 @@ subroutine inductionFactors2( BEM_Mod, B, r, chord, phi, cn, ct, Vx, Vy, drdz,ca
real(R8Ki) :: sigma_p ! local solidity (B*chord/(TwoPi*r))
real(R8Ki) :: sphi, cphi ! sin(phi), cos(phi)
real(R8Ki) :: k, kp ! non-dimensional parameters
- real(R8Ki) :: VxCorrected, kCorrectionFactor
+ real(R8Ki) :: VxCorrected, kCorrectionFactor, kpCorrectionFactor
real(R8Ki) :: effectiveYaw !
real(R8Ki) :: k0
+ real(R8Ki) :: ac !< Critical axial induction factor value above which the high thrust correction is used
real(R8Ki) :: H ! scaling factor to gradually phase out tangential induction when axial induction is near 1.0
real(R8Ki) :: fzero, a, ap ! double precision versions of output variables of similar name
@@ -741,10 +756,12 @@ subroutine inductionFactors2( BEM_Mod, B, r, chord, phi, cn, ct, Vx, Vy, drdz,ca
! "corrections"
VxCorrected = Vx*cos(cantAngle)+xVelCorr
kCorrectionFactor = 1.0_R8Ki + xVelCorr/(Vx*cos(real(cantAngle,R8Ki)))
+ kpCorrectionFactor = kCorrectionFactor
k = k*kCorrectionFactor**2
- !k = sign( k, real(phi,R8Ki) )
- k0 = a0(effectiveYaw) / (1.0-a0(effectiveYaw))
+
+ ac = ac_val(effectiveYaw)
+ k0 = ac / (1.0_R8Ki-ac)
if (.not.MomentumCorr) then
if (k <= k0 ) then
if (VxCorrected > 0.0) then
@@ -754,10 +771,11 @@ subroutine inductionFactors2( BEM_Mod, B, r, chord, phi, cn, ct, Vx, Vy, drdz,ca
end if
H = 1.0_R8Ki
else
- call axialInductionFromEmpiricalThrust( effectiveYaw, phi, k, F, a, H, MomentumCorr )
+ call axialInductionFromEmpiricalThrust( effectiveYaw, phi, k, F, a, H, skewConvention=MomentumCorr, quarticVersion=MomentumCorr )
endif
else
- call axialInductionFromGlauertMomentum(effectiveYaw, phi, k, F, a, H, MomentumCorr)
+ ! --- Using convention of axial induction where "a" is "an" (Wn = -an Un)
+ call axialInductionFromGlauertMomentum(effectiveYaw, phi, k, F, a, H)
a = sign(a,k)
endif
@@ -766,7 +784,7 @@ subroutine inductionFactors2( BEM_Mod, B, r, chord, phi, cn, ct, Vx, Vy, drdz,ca
! compute tangential induction factor:
!.....................................................
if (wakerotation) then
- call getTangentialInduction(a, cphi, sphi, Vx, F, kCorrectionFactor, sigma_p, ct, VxCorrected, effectiveYaw, H, MomentumCorr, ap, kp)
+ call getTangentialInduction(a, cphi, sphi, Vx, F, kpCorrectionFactor, sigma_p, ct, VxCorrected, effectiveYaw, H, MomentumCorr, ap, kp)
else
! we're not computing tangential induction:
@@ -800,21 +818,43 @@ subroutine inductionFactors2( BEM_Mod, B, r, chord, phi, cn, ct, Vx, Vy, drdz,ca
end subroutine inductionFactors2
-real(R8Ki) function a0(chi0)
+!> Return critical value above which the high thrust correction is applied
+!! Note: since we use the convention for a such that "Wn =- an Un" (and not Wn = - a0 U0)
+!! Then an = a0/cos(chi)
+real(R8Ki) function ac_val(chi)
implicit none
- real(R8Ki), intent(in) :: chi0
- a0 = 0.5*cos(45.0*D2R)/cos(chi0)
- a0 = min( a0, 0.5_R8Ki )
-end function a0
+ real(R8Ki), intent(in) :: chi
+ ac_val = 0.35/cos(chi) ! See e.g. Spera
+ ! NOTE: since we use continuation at a=1, we want ac_val to remain far away from 1, so we clip it
+ ac_val = min( ac_val, 0.5_R8Ki )
+end function ac_val
!-----------------------------------------------------------------------------------------
-subroutine axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, momentumCorr )
+!> Solve for `a` by equating thrust between
+!! - blade element theory (BET) and
+!! - an empirical-hight-thrust (HT) function.
+!!
+!! Assumes that the HT CT is a second order polynomial.
+!! BET = HT
+!! CT = 4kF (1-a^2) = c2 a^2 + c1 a + c0 (CT defined using Vxp) (1)
+!!
+!! Two methods of solutions are used:
+!!
+!! - Equate them and solve for a:
+!! (A-c2)a^2 - (2A +c1) a + (1-c0) =0 with A = 4kf (2)
+!!
+!! - Square (2) and solve for a in the following quartic equation:
+!! (A^2-c_2^2)a^4 + (-4A^2 - 2c_1 c_2) a^3 + (6A^2 - 2c_0 c_2 - c_1^2)a^2 + (-4A^2 -2c_0 c_1) a + (A^2-c_0^2) = 0 (3)
+!!
+!! T
+subroutine axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, quarticVersion, skewConvention )
implicit none
real(R8Ki), intent(in) :: chi0
real(ReKi), intent(in) :: phi
real(R8Ki), intent(in) :: k
real(ReKi), intent(in) :: F
- logical, intent(in) :: momentumCorr
+ logical, intent(in) :: skewConvention !< If True, assumes that "a" is "an" (Wn=-an Un) and use Glauert skew momentum. Otherwise "a" is "a0" (Wn = -a0 U0)
+ logical, intent(in) :: quarticVersion !< If True, solves for the quartic version
real(R8Ki), intent(out) :: axInd
real(R8Ki), intent(out) :: H
@@ -825,11 +865,11 @@ subroutine axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, momentu
complex(R8Ki) :: roots(4)
real(R8Ki) :: tan_chi0
! Get Coefficients for Empirical CT
- call getEmpiricalCoefficients( chi0 ,F , c0, c1, c2,momentumCorr )
+ call getEmpiricalCoefficients( chi0 ,F , c0, c1, c2, skewConvention )
! Solve for axial induction
A = 4.0*F*k
- if (.NOT.momentumCorr) then
+ if (.not.quarticVersion) then
y1 = 2.0*A + c1
y2 = 4.0*A*(c2+c1+c0) + c1*c1 - 4.0*c0*c2
y3 = 2.0*(A-c2)
@@ -843,7 +883,7 @@ subroutine axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, momentu
end if
end if
- if ((axInd>a0(chi0)).AND.(axInd<=1.0)) then
+ if ((axInd>ac_val(chi0)).AND.(axInd<=1.0)) then
H = (4.0*axInd*(1.0-axInd)*F)/(c0+c1*axInd+c2*axInd*axInd)
elseif (axInd>1.0) then
H = (-4.0*axInd*(1.0-axInd)*F)/(c0+c1*axInd+c2*axInd*axInd)
@@ -877,7 +917,7 @@ subroutine axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, momentu
if (equalrealnos(axInd,1.0_R8Ki)) then
H = 0
- elseif ((axInd>a0(chi0)).AND.(axInd<=1.0)) then
+ elseif ((axInd>ac_val(chi0)).AND.(axInd<=1.0)) then
H = 4.0_R8Ki*axInd*(1.0_R8Ki-axInd)*F*sqrt(1 + (tan_chi0/(1.0_R8Ki-axInd)*F)**2)/sqrt((c0+c1*axInd+c2*axInd*axInd)**2 + (4.0_R8Ki*axInd*tan_chi0)**2)
! Alternatively following implemention can be used but it keeps H from approaching zero as a -> 1
!H = (4.0_R8Ki*axInd*sqrt(((1.0_R8Ki-axInd)*F)**2 + tan(chi0)**2))/sqrt((c0+c1*axInd+c2*axInd*axInd)**2 + (4.0_R8Ki*axInd*tan(chi0))**2)
@@ -895,92 +935,134 @@ subroutine axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, momentu
end subroutine axialInductionFromEmpiricalThrust
-subroutine axialInductionFromGlauertMomentum(chi0, phi, k, F, axInd, H,momentumCorr)
- ! axialInductionFromGlauertMomentum calculates axial induction using Glauert Momentum Theory
- implicit none
- real(R8Ki), intent(in) :: chi0
- real(R8Ki), intent(in) :: k
- real(ReKi), intent(in) :: F
- real(ReKi), intent(in) :: phi
- logical, intent(in) :: momentumCorr
- real(R8Ki), intent(out):: axInd
- real(R8Ki), intent(out):: H
- real(R8Ki) :: c11, c12, coeffs(5), previousRoot
- complex(R8Ki) :: roots(4)
- real(R8Ki) :: a0_local
- real(R8Ki) :: c2, c1, c0 ! Empirical CT = c2*a^2 + c1*a + c0 for a > a0
- real(R8Ki) :: k0
- real(R8Ki) :: tan_chi0
-
- ! Get Coefficients for Empirical CT
- call getEmpiricalCoefficients( chi0, F, c0, c1, c2,momentumCorr)
-
- a0_local = a0(chi0)
- k0 = a0_local / (1.0-a0_local)
-
- tan_chi0 = min(MaxTanChi0, max(-MaxTanChi0, tan(chi0)))
- if (abs(k) <= k0*sqrt(1+(tan_chi0/(1-a0_local))**2)) then
- c11 = tan_chi0**2
- c12 = k**2
- coeffs(5) = 1.0_R8Ki-c12
- coeffs(4) = 4.0_R8Ki*c12-2.0_R8Ki
- coeffs(3) = 1.0_R8Ki+c11 -6.0_R8Ki*c12
- coeffs(2) = 4.0_R8Ki*c12
- coeffs(1) = -c12
-
- call QuarticRoots(coeffs,roots)
- call sortRoots(roots)
- if (phi >= 0.0) then
- if (real(roots(1))<0.0_R8Ki) then
- axInd = real(roots(2))
- else
- axInd = real(roots(1))!min(real(roots(1)),real(roots(2)))
- endif
- else
- axInd = min(real(roots(1)),real(roots(2)))
- endif
-
- previousRoot = axInd
- H = 1.0_R8Ki
- else !if (k > k0) then ! High induction/ empirical correction
- call axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, momentumCorr )
- endif
+
+!> Solve for `a` by equating thrust between:
+!! - blade element theory (BET) and
+!! - momentum theory (MT) function
+!! or
+!! - a empirical high-thrust (HT) function.
+!!
+!! At low loading, |k|kc, a hight thrust correction (2nd order polynomial) is used for "MT"
+!!
+subroutine axialInductionFromGlauertMomentum(chi0, phi, k, F, axInd, H)
+ implicit none
+ real(R8Ki), intent(in) :: chi0
+ real(R8Ki), intent(in) :: k
+ real(ReKi), intent(in) :: F
+ real(ReKi), intent(in) :: phi
+ real(R8Ki), intent(out):: axInd
+ real(R8Ki), intent(out):: H
+ real(R8Ki) :: c11, c12, coeffs(5)
+ complex(R8Ki) :: roots(4)
+ real(R8Ki) :: ac !< Critical value of the axial induction above which the high-thrust correction is applied
+ real(R8Ki) :: kc !< Critical value of the k-factor above which the high-thrust correction is applied
+ real(R8Ki) :: tan_chi0
+
+ tan_chi0 = min(MaxTanChi0, max(-MaxTanChi0, tan(chi0)))
+ ac = ac_val(chi0)
+ kc = ac / (1.0-ac) *sqrt(1+(tan_chi0/(1-ac))**2)
+ if (abs(k) <= kc) then
+ ! Use Glauert Skew Momentum (Equation 1&2), and solve for equation (3) above
+ c11 = tan_chi0**2
+ c12 = k**2
+ coeffs(5) = 1.0_R8Ki-c12
+ coeffs(4) = 4.0_R8Ki*c12-2.0_R8Ki
+ coeffs(3) = 1.0_R8Ki+c11 -6.0_R8Ki*c12
+ coeffs(2) = 4.0_R8Ki*c12
+ coeffs(1) = -c12
+
+ call QuarticRoots(coeffs,roots)
+ call sortRoots(roots)
+ if (phi >= 0.0) then
+ if (real(roots(1))<0.0_R8Ki) then
+ ! Will happen when k \in [0,1], we chose the solution of a in [0,1]
+ axInd = real(roots(2))
+ else
+ axInd = real(roots(1))!min(real(roots(1)),real(roots(2)))
+ endif
+ else
+ axInd = min(real(roots(1)),real(roots(2)))
+ endif
+ H = 1.0_R8Ki
+ else !if (k > kc) then ! High induction/ empirical correction
+ call axialInductionFromEmpiricalThrust( chi0, phi, k, F, axInd, H, skewConvention=.true., quarticVersion=.true. )
+ endif
end subroutine axialInductionFromGlauertMomentum
-subroutine getEmpiricalCoefficients( chi0, F, c0, c1, c2, MomentumCorr )
+!> Compute the coefficients of a second order polynomial that extends the Momenutm relationship CT(a)
+!! above a value a>ac. The continuation is done such that the slope and value at a=a_c match
+!! the momentum relation. The last constraint is the value of CT at a=1.
+!! Currently a hard-coded model is used for the value at at=1.
+!! The polynomial is:
+!! CT(a) = c0 + c1*a + c2*a2 a>ac
+!! obtained with the constraints:
+!! CT(a_c) = CT_c
+!! CT(1) = CT_1
+!! dCT/da(a_c) = s_c
+subroutine getEmpiricalCoefficients( chi0, F, c0, c1, c2, skewConvention )
real(R8Ki), intent(in) :: chi0
real(ReKi), intent(in) :: F
- logical, intent(in) :: MomentumCorr
+ logical, intent(in) :: skewConvention !< If True, assumes that "a" is "an" (Wn=-an Un) and use Glauert Skew Momentum. Otherwise "a" is "a0" (Wn = -a0 U0)
real(R8Ki), intent(inout) :: c0, c1, c2 ! Empirical CT = c2*a^2 + c1*a + c0 for a > a0
- real(R8Ki) :: a0_local
- real(R8Ki) :: CTata1
- real(R8Ki) :: denom, temp1, temp2
+ real(R8Ki):: c0b, c1b, c2b ! Empirical CT = c2*a^2 + c1*a + c0 for a > a0
+ real(R8Ki) :: ac
+ real(R8Ki) :: CT_1, CT_c
+ real(R8Ki) :: s_c !< Slope at a=ac
+ real(R8Ki) :: denom, tanchi2
! Empirical CT = 4*a*(1-a)*F = c2*a^2 + c1*a + c0 for a > a0
- ! third Boundary condition (CT@a=1) is based on equations from Bladed.
- a0_local = a0(chi0)
- denom = (a0_local**2 - 2.0_R8Ki*a0_local + 1.0_R8Ki)
- if (MomentumCorr) then
- temp2 = (min(MaxTanChi0, max(-MaxTanChi0, tan(chi0))))**2
- temp1 = sqrt((a0_local-1)**2 +temp2)
-
- CTata1 = sqrt(((-0.64755/(cos(chi0)*cos(chi0)) - 0.8509/cos(chi0) + 3.4984)*F)**2 + 16*temp2)
- CTata1 = max( 1.0_R8Ki, CTata1 )
-
- c2 = (CTata1 - 4*F/temp1 + 16*F*a0_local/temp1 - 4*F*a0_local*temp1 - 4*temp2*F/temp1 - 20*F*(a0_local**2)/temp1 + 8*F*(a0_local**3)/temp1 + 4*temp2*F*a0_local/temp1 ) /denom
- c1 = 2*( 2*F/temp1 - a0_local*CTata1 - 6*F*a0_local/temp1 + 2*temp2*F/temp1 + 2*F*(a0_local**2)/temp1 + 4*F*(a0_local**2)*temp1 + 6*F*(a0_local**3)/temp1 - 4*F*(a0_local**4)/temp1 - 2*temp2*F*(a0_local**2)/temp1 )/denom
- c0 = a0_local*( a0_local*CTata1 - 4*F/temp1 + 4*F*temp1 + 16*F*a0_local/temp1 - 8*F*a0_local*temp1 - 4*temp2*F/temp1 - 20*F*(a0_local**2)/temp1 + 8*F*(a0_local**3)/temp1 + 4*temp2*F*a0_local/temp1 )/denom
-
+ ac = ac_val(chi0) ! critical value above which we extent momentum theory with a 2nd order polynomial
+ if (skewConvention) then
+ ! Continuation of Glauert Skew Momentum CT= 4 a F sqrt( (1-a)^2 + tan(chi)^2 )
+ ! Using a second
+ tanchi2 = (min(MaxTanChi0, max(-MaxTanChi0, tan(chi0))))**2
+ CT_c = 4._R8Ki*F*ac * sqrt( (1._R8Ki-ac)**2 + tanchi2 ) ! CT(ac)
+ s_c = 4._R8Ki*F*(1._R8Ki-3*ac+2._R8Ki*ac**2+tanchi2)/sqrt( (1-ac)**2 + tanchi2 ) ! dCT/da(ac) (slope)
+ ! Note: model below may change
+ CT_1 = 2.0_R8Ki + 2.113_R8Ki*tanchi2**0.7635 ! CT(1)
+ CT_1 = max(CT_1, CT_c + s_c * (1._R8Ki-ac) + 0.001_R8Ki ) ! Make sure c2>0
else
- CTata1 = (-0.64755/(cos(chi0)*cos(chi0)) - 0.8509/cos(chi0) + 3.4984)*F
- CTata1 = max( 1.0_R8Ki, CTata1 )
- c2 = (-4.0_R8Ki*F*a0_local**2 + 8.0_R8Ki*F*a0_local - 4.0_R8Ki*F + CTata1)/denom
- c1 = 2.0_R8Ki*(2.0_R8Ki*F*a0_local**2 - CTata1*a0_local - 4.0_R8Ki*F*a0_local + 2.0_R8Ki*F)/denom
- c0 = CTata1*(a0_local**2)/denom
+ ! Continuation of Glauert Momentum CT= 4 a F (1-a)
+ CT_c = 4._R8Ki*F*ac * (1._R8Ki-ac) ! CT(ac)
+ s_c = 4._R8Ki*F*(1._R8Ki-2._R8Ki*ac) ! dCT/da(ac) (slope)
+ ! Note: model below may change
+ CT_1 = 2.0_R8Ki ! CT(1)
endif
-
+ call secondOrderCoeffC1(ac, s_c, CT_c, CT_1, c0, c1, c2)
end subroutine getEmpiricalCoefficients
+
+!> Compute the polynomial coefficients for a second-order polynomial such that:
+!! CT(a) = c0 + c1*a + c2*a2
+!! with the following constraints to make it C1-continuous at a=ac
+!! CT(a_c) = CT_c
+!! dCT/da(a_c) = s_c
+!! and a constraint at a=1
+!! CT(1) = CT_1
+!! The 3 coefficients are entirely determined from the three constraints
+subroutine secondOrderCoeffC1(a_c, s_c, CT_c, CT_1, c0, c1,c2)
+ real(R8Ki), intent(in ) :: a_c !< value of a above which C1-continuation is sought
+ real(R8Ki), intent(in ) :: s_c !< dCT/da(a_c), slope at a=a_c
+ real(R8Ki), intent(in ) :: CT_c !< CT(a_c), value at a=a_c
+ real(R8Ki), intent(in ) :: CT_1 !< CT(1), value at a=1
+ real(R8Ki), intent(out) :: c0, c1, c2 !< coefficients of the second order polynomial
+ real(R8Ki) :: denom
+ denom = (a_c**2 - 2._R8Ki*a_c + 1.0_R8Ki)
+ c0 = (CT_1*a_c**2 - 2._R8Ki*CT_c*a_c + CT_c + a_c**2*s_c - a_c*s_c)/denom
+ c1 = (-2._R8Ki*CT_1*a_c + 2._R8Ki*CT_c*a_c - a_c**2*s_c + s_c)/denom
+ c2 = (CT_1 - CT_c + a_c*s_c - s_c)/denom
+end subroutine secondOrderCoeffC1
+
subroutine limitInductionFactors(a,ap)
real(ReKi), intent(inout) :: a ! axial induction
real(ReKi), intent(inout), optional :: ap ! tangential induction
diff --git a/modules/aerodyn/src/BEMT_Registry.txt b/modules/aerodyn/src/BEMT_Registry.txt
index cd98adc864..893fc7fdda 100644
--- a/modules/aerodyn/src/BEMT_Registry.txt
+++ b/modules/aerodyn/src/BEMT_Registry.txt
@@ -173,8 +173,8 @@ typedef ^ ^ IntKi
#
typedef ^ InputType ReKi theta {:}{:} - - "Twist angle (includes all sources of twist) [Array of size (NumBlNds,numBlades)]" rad
typedef ^ ^ ReKi chi0 - - - "Angle between the vector normal to the rotor plane and the wind vector (e.g., the yaw angle in the case of no tilt)" rad
-typedef ^ ^ ReKi psiSkewOffset - - - "Azimuth angle offset (relative to 90 deg) of the most downwind blade when chi0 is non-zero" rad
-typedef ^ ^ ReKi psi {:} - - "Azimuth angle" rad
+typedef ^ ^ ReKi psiSkewOffset - - - "Skew azimuth angle offset (relative to 90 deg) of the most downwind blade when chi0 is non-zero" rad
+typedef ^ ^ ReKi psi_s {:} - - "Skew azimuth angle" rad
typedef ^ ^ ReKi omega - - - "Angular velocity of rotor" rad/s
typedef ^ ^ ReKi TSR - - - "Tip-speed ratio (to check if BEM should be turned off)" -
typedef ^ ^ ReKi Vx {:}{:} - - "Local axial velocity at node" m/s
@@ -197,6 +197,11 @@ typedef ^ OutputType ReKi
typedef ^ ^ ReKi phi {:}{:} - - "angle between the plane of rotation and the direction of the local wind" rad
typedef ^ ^ ReKi axInduction {:}{:} - - "axial induction" -
typedef ^ ^ ReKi tanInduction {:}{:} - - "tangential induction" -
+typedef ^ ^ ReKi axInduction_qs {:}{:} - - "axial induction quasi steady" -
+typedef ^ ^ ReKi tanInduction_qs {:}{:} - - "tangential induction quasi steady" -
+typedef ^ ^ ReKi k {:}{:} - - "Factor k in blade element theory thrust coefficient" -
+typedef ^ ^ ReKi k_p {:}{:} - - "Factor kp in blade element theory torque coefficient" -
+typedef ^ ^ ReKi F {:}{:} - - "Tip/hub loss factor" -
typedef ^ ^ ReKi Re {:}{:} - - "Reynold's number" -
typedef ^ ^ ReKi AOA {:}{:} - - "angle of attack" rad
typedef ^ ^ ReKi Cx {:}{:} - - "normal force coefficient (normal to the plane, not chord) of the jth node in the kth blade" -
diff --git a/modules/aerodyn/src/BEMT_Types.f90 b/modules/aerodyn/src/BEMT_Types.f90
index afc972c2b4..13536b274c 100644
--- a/modules/aerodyn/src/BEMT_Types.f90
+++ b/modules/aerodyn/src/BEMT_Types.f90
@@ -181,8 +181,8 @@ MODULE BEMT_Types
TYPE, PUBLIC :: BEMT_InputType
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: theta !< Twist angle (includes all sources of twist) [Array of size (NumBlNds,numBlades)] [rad]
REAL(ReKi) :: chi0 !< Angle between the vector normal to the rotor plane and the wind vector (e.g., the yaw angle in the case of no tilt) [rad]
- REAL(ReKi) :: psiSkewOffset !< Azimuth angle offset (relative to 90 deg) of the most downwind blade when chi0 is non-zero [rad]
- REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: psi !< Azimuth angle [rad]
+ REAL(ReKi) :: psiSkewOffset !< Skew azimuth angle offset (relative to 90 deg) of the most downwind blade when chi0 is non-zero [rad]
+ REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: psi_s !< Skew azimuth angle [rad]
REAL(ReKi) :: omega !< Angular velocity of rotor [rad/s]
REAL(ReKi) :: TSR !< Tip-speed ratio (to check if BEM should be turned off) [-]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Vx !< Local axial velocity at node [m/s]
@@ -206,6 +206,11 @@ MODULE BEMT_Types
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: phi !< angle between the plane of rotation and the direction of the local wind [rad]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: axInduction !< axial induction [-]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: tanInduction !< tangential induction [-]
+ REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: axInduction_qs !< axial induction quasi steady [-]
+ REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: tanInduction_qs !< tangential induction quasi steady [-]
+ REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: k !< Factor k in blade element theory thrust coefficient [-]
+ REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: k_p !< Factor kp in blade element theory torque coefficient [-]
+ REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F !< Tip/hub loss factor [-]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Re !< Reynold's number [-]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AOA !< angle of attack [rad]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Cx !< normal force coefficient (normal to the plane, not chord) of the jth node in the kth blade [-]
@@ -4912,17 +4917,17 @@ SUBROUTINE BEMT_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg
ENDIF
DstInputData%chi0 = SrcInputData%chi0
DstInputData%psiSkewOffset = SrcInputData%psiSkewOffset
-IF (ALLOCATED(SrcInputData%psi)) THEN
- i1_l = LBOUND(SrcInputData%psi,1)
- i1_u = UBOUND(SrcInputData%psi,1)
- IF (.NOT. ALLOCATED(DstInputData%psi)) THEN
- ALLOCATE(DstInputData%psi(i1_l:i1_u),STAT=ErrStat2)
+IF (ALLOCATED(SrcInputData%psi_s)) THEN
+ i1_l = LBOUND(SrcInputData%psi_s,1)
+ i1_u = UBOUND(SrcInputData%psi_s,1)
+ IF (.NOT. ALLOCATED(DstInputData%psi_s)) THEN
+ ALLOCATE(DstInputData%psi_s(i1_l:i1_u),STAT=ErrStat2)
IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%psi.', ErrStat, ErrMsg,RoutineName)
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%psi_s.', ErrStat, ErrMsg,RoutineName)
RETURN
END IF
END IF
- DstInputData%psi = SrcInputData%psi
+ DstInputData%psi_s = SrcInputData%psi_s
ENDIF
DstInputData%omega = SrcInputData%omega
DstInputData%TSR = SrcInputData%TSR
@@ -5095,8 +5100,8 @@ SUBROUTINE BEMT_DestroyInput( InputData, ErrStat, ErrMsg, DEALLOCATEpointers )
IF (ALLOCATED(InputData%theta)) THEN
DEALLOCATE(InputData%theta)
ENDIF
-IF (ALLOCATED(InputData%psi)) THEN
- DEALLOCATE(InputData%psi)
+IF (ALLOCATED(InputData%psi_s)) THEN
+ DEALLOCATE(InputData%psi_s)
ENDIF
IF (ALLOCATED(InputData%Vx)) THEN
DEALLOCATE(InputData%Vx)
@@ -5172,10 +5177,10 @@ SUBROUTINE BEMT_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg,
END IF
Re_BufSz = Re_BufSz + 1 ! chi0
Re_BufSz = Re_BufSz + 1 ! psiSkewOffset
- Int_BufSz = Int_BufSz + 1 ! psi allocated yes/no
- IF ( ALLOCATED(InData%psi) ) THEN
- Int_BufSz = Int_BufSz + 2*1 ! psi upper/lower bounds for each dimension
- Re_BufSz = Re_BufSz + SIZE(InData%psi) ! psi
+ Int_BufSz = Int_BufSz + 1 ! psi_s allocated yes/no
+ IF ( ALLOCATED(InData%psi_s) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! psi_s upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%psi_s) ! psi_s
END IF
Re_BufSz = Re_BufSz + 1 ! omega
Re_BufSz = Re_BufSz + 1 ! TSR
@@ -5283,18 +5288,18 @@ SUBROUTINE BEMT_PackInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg,
Re_Xferred = Re_Xferred + 1
ReKiBuf(Re_Xferred) = InData%psiSkewOffset
Re_Xferred = Re_Xferred + 1
- IF ( .NOT. ALLOCATED(InData%psi) ) THEN
+ IF ( .NOT. ALLOCATED(InData%psi_s) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
ELSE
IntKiBuf( Int_Xferred ) = 1
Int_Xferred = Int_Xferred + 1
- IntKiBuf( Int_Xferred ) = LBOUND(InData%psi,1)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%psi,1)
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%psi_s,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%psi_s,1)
Int_Xferred = Int_Xferred + 2
- DO i1 = LBOUND(InData%psi,1), UBOUND(InData%psi,1)
- ReKiBuf(Re_Xferred) = InData%psi(i1)
+ DO i1 = LBOUND(InData%psi_s,1), UBOUND(InData%psi_s,1)
+ ReKiBuf(Re_Xferred) = InData%psi_s(i1)
Re_Xferred = Re_Xferred + 1
END DO
END IF
@@ -5569,21 +5574,21 @@ SUBROUTINE BEMT_UnPackInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMs
Re_Xferred = Re_Xferred + 1
OutData%psiSkewOffset = ReKiBuf(Re_Xferred)
Re_Xferred = Re_Xferred + 1
- IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! psi not allocated
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! psi_s not allocated
Int_Xferred = Int_Xferred + 1
ELSE
Int_Xferred = Int_Xferred + 1
i1_l = IntKiBuf( Int_Xferred )
i1_u = IntKiBuf( Int_Xferred + 1)
Int_Xferred = Int_Xferred + 2
- IF (ALLOCATED(OutData%psi)) DEALLOCATE(OutData%psi)
- ALLOCATE(OutData%psi(i1_l:i1_u),STAT=ErrStat2)
+ IF (ALLOCATED(OutData%psi_s)) DEALLOCATE(OutData%psi_s)
+ ALLOCATE(OutData%psi_s(i1_l:i1_u),STAT=ErrStat2)
IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%psi.', ErrStat, ErrMsg,RoutineName)
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%psi_s.', ErrStat, ErrMsg,RoutineName)
RETURN
END IF
- DO i1 = LBOUND(OutData%psi,1), UBOUND(OutData%psi,1)
- OutData%psi(i1) = ReKiBuf(Re_Xferred)
+ DO i1 = LBOUND(OutData%psi_s,1), UBOUND(OutData%psi_s,1)
+ OutData%psi_s(i1) = ReKiBuf(Re_Xferred)
Re_Xferred = Re_Xferred + 1
END DO
END IF
@@ -5909,6 +5914,76 @@ SUBROUTINE BEMT_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, Err
END IF
DstOutputData%tanInduction = SrcOutputData%tanInduction
ENDIF
+IF (ALLOCATED(SrcOutputData%axInduction_qs)) THEN
+ i1_l = LBOUND(SrcOutputData%axInduction_qs,1)
+ i1_u = UBOUND(SrcOutputData%axInduction_qs,1)
+ i2_l = LBOUND(SrcOutputData%axInduction_qs,2)
+ i2_u = UBOUND(SrcOutputData%axInduction_qs,2)
+ IF (.NOT. ALLOCATED(DstOutputData%axInduction_qs)) THEN
+ ALLOCATE(DstOutputData%axInduction_qs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%axInduction_qs.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstOutputData%axInduction_qs = SrcOutputData%axInduction_qs
+ENDIF
+IF (ALLOCATED(SrcOutputData%tanInduction_qs)) THEN
+ i1_l = LBOUND(SrcOutputData%tanInduction_qs,1)
+ i1_u = UBOUND(SrcOutputData%tanInduction_qs,1)
+ i2_l = LBOUND(SrcOutputData%tanInduction_qs,2)
+ i2_u = UBOUND(SrcOutputData%tanInduction_qs,2)
+ IF (.NOT. ALLOCATED(DstOutputData%tanInduction_qs)) THEN
+ ALLOCATE(DstOutputData%tanInduction_qs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%tanInduction_qs.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstOutputData%tanInduction_qs = SrcOutputData%tanInduction_qs
+ENDIF
+IF (ALLOCATED(SrcOutputData%k)) THEN
+ i1_l = LBOUND(SrcOutputData%k,1)
+ i1_u = UBOUND(SrcOutputData%k,1)
+ i2_l = LBOUND(SrcOutputData%k,2)
+ i2_u = UBOUND(SrcOutputData%k,2)
+ IF (.NOT. ALLOCATED(DstOutputData%k)) THEN
+ ALLOCATE(DstOutputData%k(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%k.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstOutputData%k = SrcOutputData%k
+ENDIF
+IF (ALLOCATED(SrcOutputData%k_p)) THEN
+ i1_l = LBOUND(SrcOutputData%k_p,1)
+ i1_u = UBOUND(SrcOutputData%k_p,1)
+ i2_l = LBOUND(SrcOutputData%k_p,2)
+ i2_u = UBOUND(SrcOutputData%k_p,2)
+ IF (.NOT. ALLOCATED(DstOutputData%k_p)) THEN
+ ALLOCATE(DstOutputData%k_p(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%k_p.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstOutputData%k_p = SrcOutputData%k_p
+ENDIF
+IF (ALLOCATED(SrcOutputData%F)) THEN
+ i1_l = LBOUND(SrcOutputData%F,1)
+ i1_u = UBOUND(SrcOutputData%F,1)
+ i2_l = LBOUND(SrcOutputData%F,2)
+ i2_u = UBOUND(SrcOutputData%F,2)
+ IF (.NOT. ALLOCATED(DstOutputData%F)) THEN
+ ALLOCATE(DstOutputData%F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%F.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstOutputData%F = SrcOutputData%F
+ENDIF
IF (ALLOCATED(SrcOutputData%Re)) THEN
i1_l = LBOUND(SrcOutputData%Re,1)
i1_u = UBOUND(SrcOutputData%Re,1)
@@ -6126,6 +6201,21 @@ SUBROUTINE BEMT_DestroyOutput( OutputData, ErrStat, ErrMsg, DEALLOCATEpointers )
IF (ALLOCATED(OutputData%tanInduction)) THEN
DEALLOCATE(OutputData%tanInduction)
ENDIF
+IF (ALLOCATED(OutputData%axInduction_qs)) THEN
+ DEALLOCATE(OutputData%axInduction_qs)
+ENDIF
+IF (ALLOCATED(OutputData%tanInduction_qs)) THEN
+ DEALLOCATE(OutputData%tanInduction_qs)
+ENDIF
+IF (ALLOCATED(OutputData%k)) THEN
+ DEALLOCATE(OutputData%k)
+ENDIF
+IF (ALLOCATED(OutputData%k_p)) THEN
+ DEALLOCATE(OutputData%k_p)
+ENDIF
+IF (ALLOCATED(OutputData%F)) THEN
+ DEALLOCATE(OutputData%F)
+ENDIF
IF (ALLOCATED(OutputData%Re)) THEN
DEALLOCATE(OutputData%Re)
ENDIF
@@ -6222,6 +6312,31 @@ SUBROUTINE BEMT_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg,
Int_BufSz = Int_BufSz + 2*2 ! tanInduction upper/lower bounds for each dimension
Re_BufSz = Re_BufSz + SIZE(InData%tanInduction) ! tanInduction
END IF
+ Int_BufSz = Int_BufSz + 1 ! axInduction_qs allocated yes/no
+ IF ( ALLOCATED(InData%axInduction_qs) ) THEN
+ Int_BufSz = Int_BufSz + 2*2 ! axInduction_qs upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%axInduction_qs) ! axInduction_qs
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! tanInduction_qs allocated yes/no
+ IF ( ALLOCATED(InData%tanInduction_qs) ) THEN
+ Int_BufSz = Int_BufSz + 2*2 ! tanInduction_qs upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%tanInduction_qs) ! tanInduction_qs
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! k allocated yes/no
+ IF ( ALLOCATED(InData%k) ) THEN
+ Int_BufSz = Int_BufSz + 2*2 ! k upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%k) ! k
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! k_p allocated yes/no
+ IF ( ALLOCATED(InData%k_p) ) THEN
+ Int_BufSz = Int_BufSz + 2*2 ! k_p upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%k_p) ! k_p
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! F allocated yes/no
+ IF ( ALLOCATED(InData%F) ) THEN
+ Int_BufSz = Int_BufSz + 2*2 ! F upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%F) ! F
+ END IF
Int_BufSz = Int_BufSz + 1 ! Re allocated yes/no
IF ( ALLOCATED(InData%Re) ) THEN
Int_BufSz = Int_BufSz + 2*2 ! Re upper/lower bounds for each dimension
@@ -6394,6 +6509,106 @@ SUBROUTINE BEMT_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg,
END DO
END DO
END IF
+ IF ( .NOT. ALLOCATED(InData%axInduction_qs) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%axInduction_qs,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%axInduction_qs,1)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%axInduction_qs,2)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%axInduction_qs,2)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i2 = LBOUND(InData%axInduction_qs,2), UBOUND(InData%axInduction_qs,2)
+ DO i1 = LBOUND(InData%axInduction_qs,1), UBOUND(InData%axInduction_qs,1)
+ ReKiBuf(Re_Xferred) = InData%axInduction_qs(i1,i2)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%tanInduction_qs) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%tanInduction_qs,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tanInduction_qs,1)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%tanInduction_qs,2)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%tanInduction_qs,2)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i2 = LBOUND(InData%tanInduction_qs,2), UBOUND(InData%tanInduction_qs,2)
+ DO i1 = LBOUND(InData%tanInduction_qs,1), UBOUND(InData%tanInduction_qs,1)
+ ReKiBuf(Re_Xferred) = InData%tanInduction_qs(i1,i2)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%k) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%k,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%k,1)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%k,2)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%k,2)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i2 = LBOUND(InData%k,2), UBOUND(InData%k,2)
+ DO i1 = LBOUND(InData%k,1), UBOUND(InData%k,1)
+ ReKiBuf(Re_Xferred) = InData%k(i1,i2)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%k_p) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%k_p,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%k_p,1)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%k_p,2)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%k_p,2)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i2 = LBOUND(InData%k_p,2), UBOUND(InData%k_p,2)
+ DO i1 = LBOUND(InData%k_p,1), UBOUND(InData%k_p,1)
+ ReKiBuf(Re_Xferred) = InData%k_p(i1,i2)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%F) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%F,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,1)
+ Int_Xferred = Int_Xferred + 2
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%F,2)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%F,2)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i2 = LBOUND(InData%F,2), UBOUND(InData%F,2)
+ DO i1 = LBOUND(InData%F,1), UBOUND(InData%F,1)
+ ReKiBuf(Re_Xferred) = InData%F(i1,i2)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
IF ( .NOT. ALLOCATED(InData%Re) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
@@ -6776,6 +6991,121 @@ SUBROUTINE BEMT_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrM
END DO
END DO
END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! axInduction_qs not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i2_l = IntKiBuf( Int_Xferred )
+ i2_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%axInduction_qs)) DEALLOCATE(OutData%axInduction_qs)
+ ALLOCATE(OutData%axInduction_qs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%axInduction_qs.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i2 = LBOUND(OutData%axInduction_qs,2), UBOUND(OutData%axInduction_qs,2)
+ DO i1 = LBOUND(OutData%axInduction_qs,1), UBOUND(OutData%axInduction_qs,1)
+ OutData%axInduction_qs(i1,i2) = ReKiBuf(Re_Xferred)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! tanInduction_qs not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i2_l = IntKiBuf( Int_Xferred )
+ i2_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%tanInduction_qs)) DEALLOCATE(OutData%tanInduction_qs)
+ ALLOCATE(OutData%tanInduction_qs(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%tanInduction_qs.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i2 = LBOUND(OutData%tanInduction_qs,2), UBOUND(OutData%tanInduction_qs,2)
+ DO i1 = LBOUND(OutData%tanInduction_qs,1), UBOUND(OutData%tanInduction_qs,1)
+ OutData%tanInduction_qs(i1,i2) = ReKiBuf(Re_Xferred)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! k not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i2_l = IntKiBuf( Int_Xferred )
+ i2_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%k)) DEALLOCATE(OutData%k)
+ ALLOCATE(OutData%k(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%k.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i2 = LBOUND(OutData%k,2), UBOUND(OutData%k,2)
+ DO i1 = LBOUND(OutData%k,1), UBOUND(OutData%k,1)
+ OutData%k(i1,i2) = ReKiBuf(Re_Xferred)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! k_p not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i2_l = IntKiBuf( Int_Xferred )
+ i2_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%k_p)) DEALLOCATE(OutData%k_p)
+ ALLOCATE(OutData%k_p(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%k_p.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i2 = LBOUND(OutData%k_p,2), UBOUND(OutData%k_p,2)
+ DO i1 = LBOUND(OutData%k_p,1), UBOUND(OutData%k_p,1)
+ OutData%k_p(i1,i2) = ReKiBuf(Re_Xferred)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! F not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ i2_l = IntKiBuf( Int_Xferred )
+ i2_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%F)) DEALLOCATE(OutData%F)
+ ALLOCATE(OutData%F(i1_l:i1_u,i2_l:i2_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%F.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i2 = LBOUND(OutData%F,2), UBOUND(OutData%F,2)
+ DO i1 = LBOUND(OutData%F,1), UBOUND(OutData%F,1)
+ OutData%F(i1,i2) = ReKiBuf(Re_Xferred)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END DO
+ END IF
IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Re not allocated
Int_Xferred = Int_Xferred + 1
ELSE
@@ -7186,10 +7516,10 @@ SUBROUTINE BEMT_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg
u_out%chi0 = u1%chi0 + b * ScaleFactor
b = -(u1%psiSkewOffset - u2%psiSkewOffset)
u_out%psiSkewOffset = u1%psiSkewOffset + b * ScaleFactor
-IF (ALLOCATED(u_out%psi) .AND. ALLOCATED(u1%psi)) THEN
- DO i1 = LBOUND(u_out%psi,1),UBOUND(u_out%psi,1)
- b = -(u1%psi(i1) - u2%psi(i1))
- u_out%psi(i1) = u1%psi(i1) + b * ScaleFactor
+IF (ALLOCATED(u_out%psi_s) .AND. ALLOCATED(u1%psi_s)) THEN
+ DO i1 = LBOUND(u_out%psi_s,1),UBOUND(u_out%psi_s,1)
+ b = -(u1%psi_s(i1) - u2%psi_s(i1))
+ u_out%psi_s(i1) = u1%psi_s(i1) + b * ScaleFactor
END DO
END IF ! check if allocated
b = -(u1%omega - u2%omega)
@@ -7360,11 +7690,11 @@ SUBROUTINE BEMT_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, Er
b = (t(3)**2*(u1%psiSkewOffset - u2%psiSkewOffset) + t(2)**2*(-u1%psiSkewOffset + u3%psiSkewOffset))* scaleFactor
c = ( (t(2)-t(3))*u1%psiSkewOffset + t(3)*u2%psiSkewOffset - t(2)*u3%psiSkewOffset ) * scaleFactor
u_out%psiSkewOffset = u1%psiSkewOffset + b + c * t_out
-IF (ALLOCATED(u_out%psi) .AND. ALLOCATED(u1%psi)) THEN
- DO i1 = LBOUND(u_out%psi,1),UBOUND(u_out%psi,1)
- b = (t(3)**2*(u1%psi(i1) - u2%psi(i1)) + t(2)**2*(-u1%psi(i1) + u3%psi(i1)))* scaleFactor
- c = ( (t(2)-t(3))*u1%psi(i1) + t(3)*u2%psi(i1) - t(2)*u3%psi(i1) ) * scaleFactor
- u_out%psi(i1) = u1%psi(i1) + b + c * t_out
+IF (ALLOCATED(u_out%psi_s) .AND. ALLOCATED(u1%psi_s)) THEN
+ DO i1 = LBOUND(u_out%psi_s,1),UBOUND(u_out%psi_s,1)
+ b = (t(3)**2*(u1%psi_s(i1) - u2%psi_s(i1)) + t(2)**2*(-u1%psi_s(i1) + u3%psi_s(i1)))* scaleFactor
+ c = ( (t(2)-t(3))*u1%psi_s(i1) + t(3)*u2%psi_s(i1) - t(2)*u3%psi_s(i1) ) * scaleFactor
+ u_out%psi_s(i1) = u1%psi_s(i1) + b + c * t_out
END DO
END IF ! check if allocated
b = (t(3)**2*(u1%omega - u2%omega) + t(2)**2*(-u1%omega + u3%omega))* scaleFactor
@@ -7607,6 +7937,46 @@ SUBROUTINE BEMT_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMs
END DO
END DO
END IF ! check if allocated
+IF (ALLOCATED(y_out%axInduction_qs) .AND. ALLOCATED(y1%axInduction_qs)) THEN
+ DO i2 = LBOUND(y_out%axInduction_qs,2),UBOUND(y_out%axInduction_qs,2)
+ DO i1 = LBOUND(y_out%axInduction_qs,1),UBOUND(y_out%axInduction_qs,1)
+ b = -(y1%axInduction_qs(i1,i2) - y2%axInduction_qs(i1,i2))
+ y_out%axInduction_qs(i1,i2) = y1%axInduction_qs(i1,i2) + b * ScaleFactor
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%tanInduction_qs) .AND. ALLOCATED(y1%tanInduction_qs)) THEN
+ DO i2 = LBOUND(y_out%tanInduction_qs,2),UBOUND(y_out%tanInduction_qs,2)
+ DO i1 = LBOUND(y_out%tanInduction_qs,1),UBOUND(y_out%tanInduction_qs,1)
+ b = -(y1%tanInduction_qs(i1,i2) - y2%tanInduction_qs(i1,i2))
+ y_out%tanInduction_qs(i1,i2) = y1%tanInduction_qs(i1,i2) + b * ScaleFactor
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%k) .AND. ALLOCATED(y1%k)) THEN
+ DO i2 = LBOUND(y_out%k,2),UBOUND(y_out%k,2)
+ DO i1 = LBOUND(y_out%k,1),UBOUND(y_out%k,1)
+ b = -(y1%k(i1,i2) - y2%k(i1,i2))
+ y_out%k(i1,i2) = y1%k(i1,i2) + b * ScaleFactor
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%k_p) .AND. ALLOCATED(y1%k_p)) THEN
+ DO i2 = LBOUND(y_out%k_p,2),UBOUND(y_out%k_p,2)
+ DO i1 = LBOUND(y_out%k_p,1),UBOUND(y_out%k_p,1)
+ b = -(y1%k_p(i1,i2) - y2%k_p(i1,i2))
+ y_out%k_p(i1,i2) = y1%k_p(i1,i2) + b * ScaleFactor
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%F) .AND. ALLOCATED(y1%F)) THEN
+ DO i2 = LBOUND(y_out%F,2),UBOUND(y_out%F,2)
+ DO i1 = LBOUND(y_out%F,1),UBOUND(y_out%F,1)
+ b = -(y1%F(i1,i2) - y2%F(i1,i2))
+ y_out%F(i1,i2) = y1%F(i1,i2) + b * ScaleFactor
+ END DO
+ END DO
+END IF ! check if allocated
IF (ALLOCATED(y_out%Re) .AND. ALLOCATED(y1%Re)) THEN
DO i2 = LBOUND(y_out%Re,2),UBOUND(y_out%Re,2)
DO i1 = LBOUND(y_out%Re,1),UBOUND(y_out%Re,1)
@@ -7806,6 +8176,51 @@ SUBROUTINE BEMT_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, E
END DO
END DO
END IF ! check if allocated
+IF (ALLOCATED(y_out%axInduction_qs) .AND. ALLOCATED(y1%axInduction_qs)) THEN
+ DO i2 = LBOUND(y_out%axInduction_qs,2),UBOUND(y_out%axInduction_qs,2)
+ DO i1 = LBOUND(y_out%axInduction_qs,1),UBOUND(y_out%axInduction_qs,1)
+ b = (t(3)**2*(y1%axInduction_qs(i1,i2) - y2%axInduction_qs(i1,i2)) + t(2)**2*(-y1%axInduction_qs(i1,i2) + y3%axInduction_qs(i1,i2)))* scaleFactor
+ c = ( (t(2)-t(3))*y1%axInduction_qs(i1,i2) + t(3)*y2%axInduction_qs(i1,i2) - t(2)*y3%axInduction_qs(i1,i2) ) * scaleFactor
+ y_out%axInduction_qs(i1,i2) = y1%axInduction_qs(i1,i2) + b + c * t_out
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%tanInduction_qs) .AND. ALLOCATED(y1%tanInduction_qs)) THEN
+ DO i2 = LBOUND(y_out%tanInduction_qs,2),UBOUND(y_out%tanInduction_qs,2)
+ DO i1 = LBOUND(y_out%tanInduction_qs,1),UBOUND(y_out%tanInduction_qs,1)
+ b = (t(3)**2*(y1%tanInduction_qs(i1,i2) - y2%tanInduction_qs(i1,i2)) + t(2)**2*(-y1%tanInduction_qs(i1,i2) + y3%tanInduction_qs(i1,i2)))* scaleFactor
+ c = ( (t(2)-t(3))*y1%tanInduction_qs(i1,i2) + t(3)*y2%tanInduction_qs(i1,i2) - t(2)*y3%tanInduction_qs(i1,i2) ) * scaleFactor
+ y_out%tanInduction_qs(i1,i2) = y1%tanInduction_qs(i1,i2) + b + c * t_out
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%k) .AND. ALLOCATED(y1%k)) THEN
+ DO i2 = LBOUND(y_out%k,2),UBOUND(y_out%k,2)
+ DO i1 = LBOUND(y_out%k,1),UBOUND(y_out%k,1)
+ b = (t(3)**2*(y1%k(i1,i2) - y2%k(i1,i2)) + t(2)**2*(-y1%k(i1,i2) + y3%k(i1,i2)))* scaleFactor
+ c = ( (t(2)-t(3))*y1%k(i1,i2) + t(3)*y2%k(i1,i2) - t(2)*y3%k(i1,i2) ) * scaleFactor
+ y_out%k(i1,i2) = y1%k(i1,i2) + b + c * t_out
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%k_p) .AND. ALLOCATED(y1%k_p)) THEN
+ DO i2 = LBOUND(y_out%k_p,2),UBOUND(y_out%k_p,2)
+ DO i1 = LBOUND(y_out%k_p,1),UBOUND(y_out%k_p,1)
+ b = (t(3)**2*(y1%k_p(i1,i2) - y2%k_p(i1,i2)) + t(2)**2*(-y1%k_p(i1,i2) + y3%k_p(i1,i2)))* scaleFactor
+ c = ( (t(2)-t(3))*y1%k_p(i1,i2) + t(3)*y2%k_p(i1,i2) - t(2)*y3%k_p(i1,i2) ) * scaleFactor
+ y_out%k_p(i1,i2) = y1%k_p(i1,i2) + b + c * t_out
+ END DO
+ END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%F) .AND. ALLOCATED(y1%F)) THEN
+ DO i2 = LBOUND(y_out%F,2),UBOUND(y_out%F,2)
+ DO i1 = LBOUND(y_out%F,1),UBOUND(y_out%F,1)
+ b = (t(3)**2*(y1%F(i1,i2) - y2%F(i1,i2)) + t(2)**2*(-y1%F(i1,i2) + y3%F(i1,i2)))* scaleFactor
+ c = ( (t(2)-t(3))*y1%F(i1,i2) + t(3)*y2%F(i1,i2) - t(2)*y3%F(i1,i2) ) * scaleFactor
+ y_out%F(i1,i2) = y1%F(i1,i2) + b + c * t_out
+ END DO
+ END DO
+END IF ! check if allocated
IF (ALLOCATED(y_out%Re) .AND. ALLOCATED(y1%Re)) THEN
DO i2 = LBOUND(y_out%Re,2),UBOUND(y_out%Re,2)
DO i1 = LBOUND(y_out%Re,1),UBOUND(y_out%Re,1)
diff --git a/modules/awae/src/AWAE.f90 b/modules/awae/src/AWAE.f90
index b640d50397..beecc09957 100644
--- a/modules/awae/src/AWAE.f90
+++ b/modules/awae/src/AWAE.f90
@@ -1455,7 +1455,7 @@ subroutine AWAE_UpdateStates( t, n, u, p, x, xd, z, OtherState, m, errStat, errM
end do
do n_hl=0, n_high_low
! Set the hub position and orientation to pass to IfW (IfW always calculates hub and disk avg vel)
- m%u_IfW_High%HubPosition = (/ p%X0_high(nt) + 0.5*p%nX_high*p%dX_high(nt), p%Y0_high(nt) + 0.5*p%nY_high*p%dY_high(nt), p%Z0_high(nt) + 0.5*p%nZ_high*p%dZ_high(nt) /)
+ m%u_IfW_High%HubPosition = (/ p%X0_high(nt) + 0.5*p%nX_high*p%dX_high(nt), p%Y0_high(nt) + 0.5*p%nY_high*p%dY_high(nt), p%Z0_high(nt) + 0.5*p%nZ_high*p%dZ_high(nt) /) - p%WT_Position(:,nt)
call Eye(m%u_IfW_High%HubOrientation,ErrStat2,ErrMsg2)
call InflowWind_CalcOutput(t+p%dt_low+n_hl*p%DT_high, m%u_IfW_High, p%IfW(nt), x%IfW(nt), xd%IfW(nt), z%IfW(nt), OtherState%IfW(nt), m%y_IfW_High, m%IfW(nt), errStat2, errMsg2)
call SetErrStat( ErrStat2, ErrMsg2, errStat, errMsg, RoutineName )
diff --git a/modules/elastodyn/src/ElastoDyn_IO.f90 b/modules/elastodyn/src/ElastoDyn_IO.f90
index c4e40d272b..698c57fe12 100644
--- a/modules/elastodyn/src/ElastoDyn_IO.f90
+++ b/modules/elastodyn/src/ElastoDyn_IO.f90
@@ -3631,6 +3631,10 @@ SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, BldFile, FurlFile, TwrFile
CALL Cleanup()
RETURN
ENDIF
+
+!FIXME: this is a hack to fix a segfault. Better logic is really needed for the nodal outputs.
+ ! Node outputs. If no blades specified set BldNd_Outs to 0 (all checks are currently done on NumOuts, not BladesOut).
+ if (InputFileData%BldNd_BladesOut <= 0) InputFileData%BldNd_NumOuts = 0
!---------------------- END OF FILE -----------------------------------------
call cleanup()
diff --git a/modules/hydrodyn/src/HydroDyn.f90 b/modules/hydrodyn/src/HydroDyn.f90
index 2c05caa186..86d5b0927c 100644
--- a/modules/hydrodyn/src/HydroDyn.f90
+++ b/modules/hydrodyn/src/HydroDyn.f90
@@ -450,7 +450,11 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I
InputFileData%Waves%WaveFieldMod = InitInp%WaveFieldMod
InputFileData%Waves%PtfmLocationX = InitInp%PtfmLocationX
InputFileData%Waves%PtfmLocationY = InitInp%PtfmLocationY
-
+
+ ! Were visualization meshes requested?
+ p%VisMeshes = InitInp%VisMeshes
+
+
! Now call each sub-module's *_Init subroutine
! to fully initialize each sub-module based on the necessary initialization data
@@ -493,6 +497,7 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I
RETURN
END IF
tmpWaveElevXY = InitInp%WaveElevXY
+ CALL MOVE_ALLOC(tmpWaveElevXY, InputFileData%Waves%WaveElevXY) ! move this back for waves2 later
ENDIF
@@ -1366,9 +1371,11 @@ SUBROUTINE HydroDyn_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, I
ELSE
InputFileData%Morison%OutSwtch = 0
END IF
+
+ ! Were visualization meshes requested?
+ InputFileData%Morison%VisMeshes = p%VisMeshes
! Initialize the Morison Element Calculations
-
CALL Morison_Init(InputFileData%Morison, u%Morison, p%Morison, x%Morison, xd%Morison, z%Morison, OtherState%Morison, &
y%Morison, m%Morison, Interval, InitOut%Morison, ErrStat2, ErrMsg2 )
CALL SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName)
@@ -2103,7 +2110,7 @@ SUBROUTINE HydroDyn_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, ErrStat,
indxStart = (iBody-1)*6+1
indxEnd = indxStart+5
- m%F_PtfmAdd(indxStart:indxEnd) = p%AddF0(:,1) - matmul(p%AddCLin(:,:,iBody), q(indxStart:indxEnd)) - matmul(p%AddBLin(:,:,iBody), qdot(indxStart:indxEnd)) - matmul(p%AddBQuad(:,:,iBody), qdotsq(indxStart:indxEnd))
+ m%F_PtfmAdd(indxStart:indxEnd) = p%AddF0(:,iBody) - matmul(p%AddCLin(:,:,iBody), q(indxStart:indxEnd)) - matmul(p%AddBLin(:,:,iBody), qdot(indxStart:indxEnd)) - matmul(p%AddBQuad(:,:,iBody), qdotsq(indxStart:indxEnd))
! Attach to the output point mesh
y%WAMITMesh%Force (:,iBody) = m%F_PtfmAdd(indxStart:indxStart+2)
diff --git a/modules/hydrodyn/src/HydroDyn.txt b/modules/hydrodyn/src/HydroDyn.txt
index 541a6dbcce..45a63e0c65 100644
--- a/modules/hydrodyn/src/HydroDyn.txt
+++ b/modules/hydrodyn/src/HydroDyn.txt
@@ -87,6 +87,7 @@ typedef ^ ^ SiKi
typedef ^ ^ INTEGER WaveFieldMod - - - "Wave field handling (-) (switch) 0: use individual HydroDyn inputs without adjustment, 1: adjust wave phases based on turbine offsets from farm origin" -
typedef ^ ^ ReKi PtfmLocationX - - - "Supplied by Driver: X coordinate of platform location in the wave field" "m"
typedef ^ ^ ReKi PtfmLocationY - - - "Supplied by Driver: Y coordinate of platform location in the wave field" "m"
+typedef ^ ^ logical VisMeshes - .false. - "Output visualization meshes" -
#
#
# Define outputs from the initialization routine here:
@@ -218,6 +219,7 @@ typedef ^ ^ Integer
typedef ^ ^ R8Ki du {:} - - "vector that determines size of perturbation for u (inputs)" -
typedef ^ ^ R8Ki dx {:} - - "vector that determines size of perturbation for x (continuous states)" -
typedef ^ ^ Integer Jac_ny - - - "number of outputs in jacobian matrix" -
+typedef ^ ^ logical VisMeshes - .false. - "Output visualization meshes" -
#
#
# ..... Inputs ....................................................................................................................
diff --git a/modules/hydrodyn/src/HydroDyn_Types.f90 b/modules/hydrodyn/src/HydroDyn_Types.f90
index 4777387fd3..f0bbf9b23a 100644
--- a/modules/hydrodyn/src/HydroDyn_Types.f90
+++ b/modules/hydrodyn/src/HydroDyn_Types.f90
@@ -98,6 +98,7 @@ MODULE HydroDyn_Types
INTEGER(IntKi) :: WaveFieldMod !< Wave field handling (-) (switch) 0: use individual HydroDyn inputs without adjustment, 1: adjust wave phases based on turbine offsets from farm origin [-]
REAL(ReKi) :: PtfmLocationX !< Supplied by Driver: X coordinate of platform location in the wave field [m]
REAL(ReKi) :: PtfmLocationY !< Supplied by Driver: Y coordinate of platform location in the wave field [m]
+ LOGICAL :: VisMeshes = .false. !< Output visualization meshes [-]
END TYPE HydroDyn_InitInputType
! =======================
! ========= HydroDyn_InitOutputType =======
@@ -224,6 +225,7 @@ MODULE HydroDyn_Types
REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: du !< vector that determines size of perturbation for u (inputs) [-]
REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: dx !< vector that determines size of perturbation for x (continuous states) [-]
INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix [-]
+ LOGICAL :: VisMeshes = .false. !< Output visualization meshes [-]
END TYPE HydroDyn_ParameterType
! =======================
! ========= HydroDyn_InputType =======
@@ -1963,6 +1965,7 @@ SUBROUTINE HydroDyn_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode,
DstInitInputData%WaveFieldMod = SrcInitInputData%WaveFieldMod
DstInitInputData%PtfmLocationX = SrcInitInputData%PtfmLocationX
DstInitInputData%PtfmLocationY = SrcInitInputData%PtfmLocationY
+ DstInitInputData%VisMeshes = SrcInitInputData%VisMeshes
END SUBROUTINE HydroDyn_CopyInitInput
SUBROUTINE HydroDyn_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers )
@@ -2064,6 +2067,7 @@ SUBROUTINE HydroDyn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat,
Int_BufSz = Int_BufSz + 1 ! WaveFieldMod
Re_BufSz = Re_BufSz + 1 ! PtfmLocationX
Re_BufSz = Re_BufSz + 1 ! PtfmLocationY
+ Int_BufSz = Int_BufSz + 1 ! VisMeshes
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
IF (ErrStat2 /= 0) THEN
@@ -2169,6 +2173,8 @@ SUBROUTINE HydroDyn_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat,
Re_Xferred = Re_Xferred + 1
ReKiBuf(Re_Xferred) = InData%PtfmLocationY
Re_Xferred = Re_Xferred + 1
+ IntKiBuf(Int_Xferred) = TRANSFER(InData%VisMeshes, IntKiBuf(1))
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE HydroDyn_PackInitInput
SUBROUTINE HydroDyn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
@@ -2292,6 +2298,8 @@ SUBROUTINE HydroDyn_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta
Re_Xferred = Re_Xferred + 1
OutData%PtfmLocationY = ReKiBuf(Re_Xferred)
Re_Xferred = Re_Xferred + 1
+ OutData%VisMeshes = TRANSFER(IntKiBuf(Int_Xferred), OutData%VisMeshes)
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE HydroDyn_UnPackInitInput
SUBROUTINE HydroDyn_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg )
@@ -8122,6 +8130,7 @@ SUBROUTINE HydroDyn_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Er
DstParamData%dx = SrcParamData%dx
ENDIF
DstParamData%Jac_ny = SrcParamData%Jac_ny
+ DstParamData%VisMeshes = SrcParamData%VisMeshes
END SUBROUTINE HydroDyn_CopyParam
SUBROUTINE HydroDyn_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers )
@@ -8421,6 +8430,7 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM
Db_BufSz = Db_BufSz + SIZE(InData%dx) ! dx
END IF
Int_BufSz = Int_BufSz + 1 ! Jac_ny
+ Int_BufSz = Int_BufSz + 1 ! VisMeshes
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
IF (ErrStat2 /= 0) THEN
@@ -8897,6 +8907,8 @@ SUBROUTINE HydroDyn_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM
END IF
IntKiBuf(Int_Xferred) = InData%Jac_ny
Int_Xferred = Int_Xferred + 1
+ IntKiBuf(Int_Xferred) = TRANSFER(InData%VisMeshes, IntKiBuf(1))
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE HydroDyn_PackParam
SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
@@ -9479,6 +9491,8 @@ SUBROUTINE HydroDyn_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E
END IF
OutData%Jac_ny = IntKiBuf(Int_Xferred)
Int_Xferred = Int_Xferred + 1
+ OutData%VisMeshes = TRANSFER(IntKiBuf(Int_Xferred), OutData%VisMeshes)
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE HydroDyn_UnPackParam
SUBROUTINE HydroDyn_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg )
diff --git a/modules/hydrodyn/src/Morison.f90 b/modules/hydrodyn/src/Morison.f90
index 0d834adfa5..35c1a11dbe 100644
--- a/modules/hydrodyn/src/Morison.f90
+++ b/modules/hydrodyn/src/Morison.f90
@@ -1892,6 +1892,7 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In
p%NMOutputs = InitInp%NMOutputs ! Number of members to output [ >=0 and <10]
p%OutSwtch = InitInp%OutSwtch
p%MSL2SWL = InitInp%MSL2SWL
+ p%VisMeshes = InitInp%VisMeshes ! visualization mesh for morison elements
ALLOCATE ( p%MOutLst(p%NMOutputs), STAT = errStat )
IF ( errStat /= ErrID_None ) THEN
@@ -2180,11 +2181,18 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In
END IF
+ ! visualization Line2 mesh
+ if (p%VisMeshes) then
+ call VisMeshSetup(u,p,y,m,InitOut,ErrStat2,ErrMsg2); call SetErrStat( ErrStat2, ErrMsg2, errStat, errMsg, 'Morison_Init' )
+ if ( errStat >= AbortErrLev ) return
+ endif
+
! We will call CalcOutput to compute the loads for the initial reference position
! Then we can use the computed load components in the Summary File
! NOTE: Morison module has no states, otherwise we could no do this. GJH
call Morison_CalcOutput(0.0_DbKi, u, p, x, xd, z, OtherState, y, m, errStat, errMsg )
+ IF ( errStat > AbortErrLev ) RETURN
! Write Summary information now that everything has been initialized.
CALL WriteSummaryFile( InitInp%UnSum, InitInp%Gravity, InitInp%MSL2SWL, InitInp%WtrDpth, InitInp%NJoints, InitInp%NNodes, InitInp%Nodes, p%NMembers, p%Members, &
@@ -2198,6 +2206,106 @@ SUBROUTINE Morison_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, In
! END SUBROUTINE
END SUBROUTINE Morison_Init
+subroutine VisMeshSetup(u,p,y,m,InitOut,ErrStat,ErrMsg)
+ type(Morison_InputType), intent(inout) :: u
+ type(Morison_ParameterType), intent(in ) :: p
+ type(Morison_OutputType), intent(inout) :: y
+ type(Morison_MiscVarType), intent(inout) :: m
+ type(Morison_InitOutputType), intent(inout) :: InitOut
+ integer(IntKi), intent( out) :: ErrStat
+ character(*), intent( out) :: ErrMsg
+
+ integer(IntKi) :: TotNodes ! total nodes in all elements (may differ from p%NNodes due to overlaps)
+ integer(IntKi) :: TotElems ! total number of elements
+ integer(IntKi) :: NdIdx, iMem, iNd, NdNum ! indexing
+ real(ReKi) :: NdPos(3),Pos1(3),Pos2(3)
+ real(R8Ki) :: MemberOrient(3,3)
+ real(R8Ki) :: Theta(3) ! Euler rotations
+ integer(IntKi) :: ErrStat2
+ character(ErrMsgLen) :: ErrMsg2
+ character(*), parameter :: RoutineName = 'VisMeshSetup'
+
+ ErrStat = ErrID_None
+ ErrMsg = ""
+
+ ! Total number of nodes = sum of all member nodes
+ ! Total number of elements = sum of all member elements
+ TotNodes=0
+ TotElems=0
+ do iMem=1,size(p%Members)
+ TotElems = TotElems + p%Members(iMem)%NElements
+ TotNodes = TotNodes + size(p%Members(iMem)%NodeIndx)
+ enddo
+
+ ! Storage for the radius associated with each node
+ call AllocAry( InitOut%MorisonVisRad, TotNodes, 'MorisonVisRad', ErrStat2, ErrMsg2)
+ if (Failed()) return
+
+ call MeshCreate( BlankMesh = y%VisMesh, &
+ IOS = COMPONENT_OUTPUT, &
+ Nnodes = TotNodes, &
+ ErrStat = ErrStat2, &
+ ErrMess = ErrMsg2, &
+ TranslationDisp = .TRUE., &
+ Orientation = .TRUE. )
+ if (Failed()) return
+
+ ! Position the nodes
+ NdNum=0 ! node number in y%VisMesh
+ do iMem=1,size(p%Members)
+
+!FIXME:MemberOrient This is not correct for non-circular or curved members
+ ! calculate an orientation using yaw-pitch-roll sequence with roll defined as zero (insufficient info)
+ Pos1=u%Mesh%Position(:,p%Members(iMem)%NodeIndx(1)) ! start node position of member
+ Pos2=u%Mesh%Position(:,p%Members(iMem)%NodeIndx(size(p%Members(iMem)%NodeIndx))) ! end node position of member
+ Theta(1) = 0.0_R8Ki ! roll (assumed since insufficient info)
+ Theta(2) = acos(real((Pos2(3)-Pos1(3))/norm2(Pos2-Pos1),R8Ki)) ! pitch
+ Theta(3) = atan2(real(Pos2(2)-Pos1(2),R8Ki),real(Pos2(1)-Pos1(1),R8Ki)) ! yaw
+ MemberOrient=EulerConstructZYX(Theta) ! yaw-pitch-roll sequence
+
+ ! Set mesh postion, orientation, and radius
+ do iNd=1,size(p%Members(iMem)%NodeIndx)
+ NdNum=NdNum+1 ! node number in y%VisMesh
+ NdIdx = p%Members(iMem)%NodeIndx(iNd) ! node number in u%Mesh
+ NdPos = u%Mesh%Position(:,NdIdx) ! node position
+ call MeshPositionNode (y%VisMesh, NdNum, u%Mesh%Position(:,NdIdx), ErrStat2, ErrMsg2, Orient=MemberOrient)
+ if (Failed()) return
+ InitOut%MorisonVisRad(NdNum) = p%Members(iMem)%RMG(iNd) ! radius (including marine growth) for visualization
+ enddo
+ enddo
+
+ ! make elements (line nodes start at 0 index, so N+1 total nodes)
+ NdNum=0 ! node number in y%VisMesh
+ do iMem=1,size(p%Members)
+ do iNd=1,size(p%Members(iMem)%NodeIndx)
+ NdNum=NdNum+1 ! node number in y%VisMesh
+ if (iNd==1) cycle
+ call MeshConstructElement ( Mesh = y%VisMesh, &
+ Xelement = ELEMENT_LINE2, &
+ P1=NdNum-1, P2=NdNum, & ! nodes to connect
+ errStat = ErrStat2, &
+ ErrMess = ErrMsg2 )
+ if (Failed()) return
+ enddo
+ enddo
+
+ ! commit the assembled mesh
+ call MeshCommit ( y%VisMesh, ErrStat2, ErrMsg2)
+ if (Failed()) return
+
+ ! map the mesh to u%Mesh
+ call MeshMapCreate( u%Mesh, y%VisMesh, m%VisMeshMap, ErrStat2, ErrMsg2 )
+ if (Failed()) return
+
+contains
+ logical function Failed()
+ CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName )
+ Failed = ErrStat >= AbortErrLev
+ !if (Failed) then
+ ! call FailCleanup()
+ !endif
+ end function Failed
+end subroutine VisMeshSetup
SUBROUTINE RodrigMat(a, R, errStat, errMsg)
@@ -3313,8 +3421,15 @@ SUBROUTINE Morison_CalcOutput( Time, u, p, x, xd, z, OtherState, y, m, errStat,
CALL MrsnOut_WriteOutputs( p%UnOutFile, Time, y, p, errStat, errMsg )
END IF
END IF
-
-
+
+
+ ! map the motion to the visulization mesh
+ if (p%VisMeshes) then
+ !FIXME: error handling is incorrect here (overwrites all previous errors/warnings)
+ call Transfer_Point_to_Line2( u%Mesh, y%VisMesh, m%VisMeshMap, ErrStat, ErrMsg )
+ endif
+
+
END SUBROUTINE Morison_CalcOutput
subroutine LumpDistrHydroLoads( f_hydro, k_hat, dl, h_c, lumpedLoad )
diff --git a/modules/hydrodyn/src/Morison.txt b/modules/hydrodyn/src/Morison.txt
index 2943d32c35..c59db0b043 100644
--- a/modules/hydrodyn/src/Morison.txt
+++ b/modules/hydrodyn/src/Morison.txt
@@ -256,12 +256,13 @@ typedef ^ ^ SiKi
typedef ^ ^ SiKi WaveDynP {:}{:} - - "" -
typedef ^ ^ SiKi WaveVel {:}{:}{:} - - "" -
typedef ^ ^ INTEGER nodeInWater {:}{:} - - "Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated" -
+typedef ^ ^ logical VisMeshes - .false. - "Output visualization meshes" -
#
#
# Define outputs from the initialization routine here:
#
#typedef ^ InitOutputType MeshType Mesh - - - "Unused?" -
-#typedef ^ ^ SiKi Morison_Rad {:} - - "radius of node (for FAST visualization)" (m)
+typedef ^ InitOutputType SiKi MorisonVisRad {:} - - "radius of node (for FAST visualization)" (m)
typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "User-requested Output channel names" -
typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "" -
#
@@ -310,6 +311,7 @@ typedef ^ ^ ReKi
typedef ^ ^ ReKi F_A_End {:}{:} - - "Lumped added mass loads at time t, which may not correspond to the WaveTime array of times" -
typedef ^ ^ ReKi F_BF_End {:}{:} - - "" -
typedef ^ ^ INTEGER LastIndWave - - - "Last time index used in the wave kinematics arrays" -
+typedef ^ ^ MeshMapType VisMeshMap - - - "Mesh mapping for visualization mesh" -
# ..... Parameters ................................................................................................................
# Define parameters here:
@@ -349,6 +351,7 @@ typedef ^ ^ INTEGER
typedef ^ ^ CHARACTER(20) OutFmt - - - "" -
typedef ^ ^ CHARACTER(20) OutSFmt - - - "" -
typedef ^ ^ CHARACTER(ChanLen) Delim - - - "" -
+typedef ^ ^ logical VisMeshes - .false. - "Output visualization meshes" -
#
#
# ..... Inputs ....................................................................................................................
@@ -360,4 +363,5 @@ typedef ^ InputType MeshType
# ..... Outputs ...................................................................................................................
# Define outputs that are contained on the mesh here:
typedef ^ OutputType MeshType Mesh - - - "Loads on each node output mesh" -
+typedef ^ ^ MeshType VisMesh - - - "Line mesh for visualization" -
typedef ^ ^ ReKi WriteOutput {:} - - "" -
diff --git a/modules/hydrodyn/src/Morison_Types.f90 b/modules/hydrodyn/src/Morison_Types.f90
index 8f1ca39fd1..bfa9d65c53 100644
--- a/modules/hydrodyn/src/Morison_Types.f90
+++ b/modules/hydrodyn/src/Morison_Types.f90
@@ -319,10 +319,12 @@ MODULE Morison_Types
REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveDynP !< [-]
REAL(SiKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel !< [-]
INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: nodeInWater !< Logical flag indicating if the node at the given time step is in the water, and hence needs to have hydrodynamic forces calculated [-]
+ LOGICAL :: VisMeshes = .false. !< Output visualization meshes [-]
END TYPE Morison_InitInputType
! =======================
! ========= Morison_InitOutputType =======
TYPE, PUBLIC :: Morison_InitOutputType
+ REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: MorisonVisRad !< radius of node (for FAST visualization) [(m)]
CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< User-requested Output channel names [-]
CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< [-]
END TYPE Morison_InitOutputType
@@ -362,6 +364,7 @@ MODULE Morison_Types
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_A_End !< Lumped added mass loads at time t, which may not correspond to the WaveTime array of times [-]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: F_BF_End !< [-]
INTEGER(IntKi) :: LastIndWave !< Last time index used in the wave kinematics arrays [-]
+ TYPE(MeshMapType) :: VisMeshMap !< Mesh mapping for visualization mesh [-]
END TYPE Morison_MiscVarType
! =======================
! ========= Morison_ParameterType =======
@@ -400,6 +403,7 @@ MODULE Morison_Types
CHARACTER(20) :: OutFmt !< [-]
CHARACTER(20) :: OutSFmt !< [-]
CHARACTER(ChanLen) :: Delim !< [-]
+ LOGICAL :: VisMeshes = .false. !< Output visualization meshes [-]
END TYPE Morison_ParameterType
! =======================
! ========= Morison_InputType =======
@@ -410,6 +414,7 @@ MODULE Morison_Types
! ========= Morison_OutputType =======
TYPE, PUBLIC :: Morison_OutputType
TYPE(MeshType) :: Mesh !< Loads on each node output mesh [-]
+ TYPE(MeshType) :: VisMesh !< Line mesh for visualization [-]
REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< [-]
END TYPE Morison_OutputType
! =======================
@@ -6337,6 +6342,7 @@ SUBROUTINE Morison_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode,
END IF
DstInitInputData%nodeInWater = SrcInitInputData%nodeInWater
ENDIF
+ DstInitInputData%VisMeshes = SrcInitInputData%VisMeshes
END SUBROUTINE Morison_CopyInitInput
SUBROUTINE Morison_DestroyInitInput( InitInputData, ErrStat, ErrMsg, DEALLOCATEpointers )
@@ -6813,6 +6819,7 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
Int_BufSz = Int_BufSz + 2*2 ! nodeInWater upper/lower bounds for each dimension
Int_BufSz = Int_BufSz + SIZE(InData%nodeInWater) ! nodeInWater
END IF
+ Int_BufSz = Int_BufSz + 1 ! VisMeshes
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
IF (ErrStat2 /= 0) THEN
@@ -7491,6 +7498,8 @@ SUBROUTINE Morison_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, E
END DO
END DO
END IF
+ IntKiBuf(Int_Xferred) = TRANSFER(InData%VisMeshes, IntKiBuf(1))
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE Morison_PackInitInput
SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
@@ -8358,6 +8367,8 @@ SUBROUTINE Morison_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat
END DO
END DO
END IF
+ OutData%VisMeshes = TRANSFER(IntKiBuf(Int_Xferred), OutData%VisMeshes)
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE Morison_UnPackInitInput
SUBROUTINE Morison_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg )
@@ -8375,6 +8386,18 @@ SUBROUTINE Morison_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCod
!
ErrStat = ErrID_None
ErrMsg = ""
+IF (ALLOCATED(SrcInitOutputData%MorisonVisRad)) THEN
+ i1_l = LBOUND(SrcInitOutputData%MorisonVisRad,1)
+ i1_u = UBOUND(SrcInitOutputData%MorisonVisRad,1)
+ IF (.NOT. ALLOCATED(DstInitOutputData%MorisonVisRad)) THEN
+ ALLOCATE(DstInitOutputData%MorisonVisRad(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%MorisonVisRad.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstInitOutputData%MorisonVisRad = SrcInitOutputData%MorisonVisRad
+ENDIF
IF (ALLOCATED(SrcInitOutputData%WriteOutputHdr)) THEN
i1_l = LBOUND(SrcInitOutputData%WriteOutputHdr,1)
i1_u = UBOUND(SrcInitOutputData%WriteOutputHdr,1)
@@ -8422,6 +8445,9 @@ SUBROUTINE Morison_DestroyInitOutput( InitOutputData, ErrStat, ErrMsg, DEALLOCAT
DEALLOCATEpointers_local = .true.
END IF
+IF (ALLOCATED(InitOutputData%MorisonVisRad)) THEN
+ DEALLOCATE(InitOutputData%MorisonVisRad)
+ENDIF
IF (ALLOCATED(InitOutputData%WriteOutputHdr)) THEN
DEALLOCATE(InitOutputData%WriteOutputHdr)
ENDIF
@@ -8465,6 +8491,11 @@ SUBROUTINE Morison_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat,
Re_BufSz = 0
Db_BufSz = 0
Int_BufSz = 0
+ Int_BufSz = Int_BufSz + 1 ! MorisonVisRad allocated yes/no
+ IF ( ALLOCATED(InData%MorisonVisRad) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! MorisonVisRad upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%MorisonVisRad) ! MorisonVisRad
+ END IF
Int_BufSz = Int_BufSz + 1 ! WriteOutputHdr allocated yes/no
IF ( ALLOCATED(InData%WriteOutputHdr) ) THEN
Int_BufSz = Int_BufSz + 2*1 ! WriteOutputHdr upper/lower bounds for each dimension
@@ -8502,6 +8533,21 @@ SUBROUTINE Morison_PackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat,
Db_Xferred = 1
Int_Xferred = 1
+ IF ( .NOT. ALLOCATED(InData%MorisonVisRad) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%MorisonVisRad,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MorisonVisRad,1)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i1 = LBOUND(InData%MorisonVisRad,1), UBOUND(InData%MorisonVisRad,1)
+ ReKiBuf(Re_Xferred) = InData%MorisonVisRad(i1)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END IF
IF ( .NOT. ALLOCATED(InData%WriteOutputHdr) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
@@ -8565,6 +8611,24 @@ SUBROUTINE Morison_UnPackInitOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta
Re_Xferred = 1
Db_Xferred = 1
Int_Xferred = 1
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MorisonVisRad not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%MorisonVisRad)) DEALLOCATE(OutData%MorisonVisRad)
+ ALLOCATE(OutData%MorisonVisRad(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MorisonVisRad.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i1 = LBOUND(OutData%MorisonVisRad,1), UBOUND(OutData%MorisonVisRad,1)
+ OutData%MorisonVisRad(i1) = REAL(ReKiBuf(Re_Xferred), SiKi)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END IF
IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutputHdr not allocated
Int_Xferred = Int_Xferred + 1
ELSE
@@ -9156,7 +9220,7 @@ SUBROUTINE Morison_UnPackOtherState( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrSta
END SUBROUTINE Morison_UnPackOtherState
SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg )
- TYPE(Morison_MiscVarType), INTENT(IN) :: SrcMiscData
+ TYPE(Morison_MiscVarType), INTENT(INOUT) :: SrcMiscData
TYPE(Morison_MiscVarType), INTENT(INOUT) :: DstMiscData
INTEGER(IntKi), INTENT(IN ) :: CtrlCode
INTEGER(IntKi), INTENT( OUT) :: ErrStat
@@ -9338,6 +9402,9 @@ SUBROUTINE Morison_CopyMisc( SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg
DstMiscData%F_BF_End = SrcMiscData%F_BF_End
ENDIF
DstMiscData%LastIndWave = SrcMiscData%LastIndWave
+ CALL NWTC_Library_Copymeshmaptype( SrcMiscData%VisMeshMap, DstMiscData%VisMeshMap, CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
END SUBROUTINE Morison_CopyMisc
SUBROUTINE Morison_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers )
@@ -9401,6 +9468,8 @@ SUBROUTINE Morison_DestroyMisc( MiscData, ErrStat, ErrMsg, DEALLOCATEpointers )
IF (ALLOCATED(MiscData%F_BF_End)) THEN
DEALLOCATE(MiscData%F_BF_End)
ENDIF
+ CALL NWTC_Library_Destroymeshmaptype( MiscData%VisMeshMap, ErrStat2, ErrMsg2, DEALLOCATEpointers_local )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
END SUBROUTINE Morison_DestroyMisc
SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly )
@@ -9518,6 +9587,23 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg
Re_BufSz = Re_BufSz + SIZE(InData%F_BF_End) ! F_BF_End
END IF
Int_BufSz = Int_BufSz + 1 ! LastIndWave
+ Int_BufSz = Int_BufSz + 3 ! VisMeshMap: size of buffers for each call to pack subtype
+ CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%VisMeshMap, ErrStat2, ErrMsg2, .TRUE. ) ! VisMeshMap
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN ! VisMeshMap
+ Re_BufSz = Re_BufSz + SIZE( Re_Buf )
+ DEALLOCATE(Re_Buf)
+ END IF
+ IF(ALLOCATED(Db_Buf)) THEN ! VisMeshMap
+ Db_BufSz = Db_BufSz + SIZE( Db_Buf )
+ DEALLOCATE(Db_Buf)
+ END IF
+ IF(ALLOCATED(Int_Buf)) THEN ! VisMeshMap
+ Int_BufSz = Int_BufSz + SIZE( Int_Buf )
+ DEALLOCATE(Int_Buf)
+ END IF
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
IF (ErrStat2 /= 0) THEN
@@ -9798,6 +9884,34 @@ SUBROUTINE Morison_PackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg
END IF
IntKiBuf(Int_Xferred) = InData%LastIndWave
Int_Xferred = Int_Xferred + 1
+ CALL NWTC_Library_Packmeshmaptype( Re_Buf, Db_Buf, Int_Buf, InData%VisMeshMap, ErrStat2, ErrMsg2, OnlySize ) ! VisMeshMap
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf
+ Re_Xferred = Re_Xferred + SIZE(Re_Buf)
+ DEALLOCATE(Re_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Db_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf
+ Db_Xferred = Db_Xferred + SIZE(Db_Buf)
+ DEALLOCATE(Db_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Int_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf
+ Int_Xferred = Int_Xferred + SIZE(Int_Buf)
+ DEALLOCATE(Int_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
END SUBROUTINE Morison_PackMisc
SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
@@ -10129,6 +10243,46 @@ SUBROUTINE Morison_UnPackMisc( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err
END IF
OutData%LastIndWave = IntKiBuf(Int_Xferred)
Int_Xferred = Int_Xferred + 1
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )
+ Re_Xferred = Re_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )
+ Db_Xferred = Db_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )
+ Int_Xferred = Int_Xferred + Buf_size
+ END IF
+ CALL NWTC_Library_Unpackmeshmaptype( Re_Buf, Db_Buf, Int_Buf, OutData%VisMeshMap, ErrStat2, ErrMsg2 ) ! VisMeshMap
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
+ IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
+ IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
END SUBROUTINE Morison_UnPackMisc
SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg )
@@ -10400,6 +10554,7 @@ SUBROUTINE Morison_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, Err
DstParamData%OutFmt = SrcParamData%OutFmt
DstParamData%OutSFmt = SrcParamData%OutSFmt
DstParamData%Delim = SrcParamData%Delim
+ DstParamData%VisMeshes = SrcParamData%VisMeshes
END SUBROUTINE Morison_CopyParam
SUBROUTINE Morison_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers )
@@ -10695,6 +10850,7 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs
Int_BufSz = Int_BufSz + 1*LEN(InData%OutFmt) ! OutFmt
Int_BufSz = Int_BufSz + 1*LEN(InData%OutSFmt) ! OutSFmt
Int_BufSz = Int_BufSz + 1*LEN(InData%Delim) ! Delim
+ Int_BufSz = Int_BufSz + 1 ! VisMeshes
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
IF (ErrStat2 /= 0) THEN
@@ -11173,6 +11329,8 @@ SUBROUTINE Morison_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMs
IntKiBuf(Int_Xferred) = ICHAR(InData%Delim(I:I), IntKi)
Int_Xferred = Int_Xferred + 1
END DO ! I
+ IntKiBuf(Int_Xferred) = TRANSFER(InData%VisMeshes, IntKiBuf(1))
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE Morison_PackParam
SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
@@ -11751,6 +11909,8 @@ SUBROUTINE Morison_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Er
OutData%Delim(I:I) = CHAR(IntKiBuf(Int_Xferred))
Int_Xferred = Int_Xferred + 1
END DO ! I
+ OutData%VisMeshes = TRANSFER(IntKiBuf(Int_Xferred), OutData%VisMeshes)
+ Int_Xferred = Int_Xferred + 1
END SUBROUTINE Morison_UnPackParam
SUBROUTINE Morison_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg )
@@ -11993,6 +12153,9 @@ SUBROUTINE Morison_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat,
CALL MeshCopy( SrcOutputData%Mesh, DstOutputData%Mesh, CtrlCode, ErrStat2, ErrMsg2 )
CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
IF (ErrStat>=AbortErrLev) RETURN
+ CALL MeshCopy( SrcOutputData%VisMesh, DstOutputData%VisMesh, CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
IF (ALLOCATED(SrcOutputData%WriteOutput)) THEN
i1_l = LBOUND(SrcOutputData%WriteOutput,1)
i1_u = UBOUND(SrcOutputData%WriteOutput,1)
@@ -12030,6 +12193,8 @@ SUBROUTINE Morison_DestroyOutput( OutputData, ErrStat, ErrMsg, DEALLOCATEpointer
CALL MeshDestroy( OutputData%Mesh, ErrStat2, ErrMsg2 )
CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ CALL MeshDestroy( OutputData%VisMesh, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
IF (ALLOCATED(OutputData%WriteOutput)) THEN
DEALLOCATE(OutputData%WriteOutput)
ENDIF
@@ -12088,6 +12253,23 @@ SUBROUTINE Morison_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM
Int_BufSz = Int_BufSz + SIZE( Int_Buf )
DEALLOCATE(Int_Buf)
END IF
+ Int_BufSz = Int_BufSz + 3 ! VisMesh: size of buffers for each call to pack subtype
+ CALL MeshPack( InData%VisMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! VisMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN ! VisMesh
+ Re_BufSz = Re_BufSz + SIZE( Re_Buf )
+ DEALLOCATE(Re_Buf)
+ END IF
+ IF(ALLOCATED(Db_Buf)) THEN ! VisMesh
+ Db_BufSz = Db_BufSz + SIZE( Db_Buf )
+ DEALLOCATE(Db_Buf)
+ END IF
+ IF(ALLOCATED(Int_Buf)) THEN ! VisMesh
+ Int_BufSz = Int_BufSz + SIZE( Int_Buf )
+ DEALLOCATE(Int_Buf)
+ END IF
Int_BufSz = Int_BufSz + 1 ! WriteOutput allocated yes/no
IF ( ALLOCATED(InData%WriteOutput) ) THEN
Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension
@@ -12148,6 +12330,34 @@ SUBROUTINE Morison_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM
ELSE
IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
ENDIF
+ CALL MeshPack( InData%VisMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! VisMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf
+ Re_Xferred = Re_Xferred + SIZE(Re_Buf)
+ DEALLOCATE(Re_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Db_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf
+ Db_Xferred = Db_Xferred + SIZE(Db_Buf)
+ DEALLOCATE(Db_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Int_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf
+ Int_Xferred = Int_Xferred + SIZE(Int_Buf)
+ DEALLOCATE(Int_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
IF ( .NOT. ALLOCATED(InData%WriteOutput) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
@@ -12232,6 +12442,46 @@ SUBROUTINE Morison_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E
IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )
+ Re_Xferred = Re_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )
+ Db_Xferred = Db_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )
+ Int_Xferred = Int_Xferred + Buf_size
+ END IF
+ CALL MeshUnpack( OutData%VisMesh, Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! VisMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
+ IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
+ IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WriteOutput not allocated
Int_Xferred = Int_Xferred + 1
ELSE
@@ -12503,6 +12753,8 @@ SUBROUTINE Morison_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, Er
ScaleFactor = t_out / t(2)
CALL MeshExtrapInterp1(y1%Mesh, y2%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 )
CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ CALL MeshExtrapInterp1(y1%VisMesh, y2%VisMesh, tin, y_out%VisMesh, tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN
DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1)
b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1))
@@ -12568,6 +12820,8 @@ SUBROUTINE Morison_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat
ScaleFactor = t_out / (t(2) * t(3) * (t(2) - t(3)))
CALL MeshExtrapInterp2(y1%Mesh, y2%Mesh, y3%Mesh, tin, y_out%Mesh, tin_out, ErrStat2, ErrMsg2 )
CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ CALL MeshExtrapInterp2(y1%VisMesh, y2%VisMesh, y3%VisMesh, tin, y_out%VisMesh, tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN
DO i1 = LBOUND(y_out%WriteOutput,1),UBOUND(y_out%WriteOutput,1)
b = (t(3)**2*(y1%WriteOutput(i1) - y2%WriteOutput(i1)) + t(2)**2*(-y1%WriteOutput(i1) + y3%WriteOutput(i1)))* scaleFactor
diff --git a/modules/inflowwind/src/IfW_FlowField.f90 b/modules/inflowwind/src/IfW_FlowField.f90
index 0d07e55f5d..a71b75dffc 100644
--- a/modules/inflowwind/src/IfW_FlowField.f90
+++ b/modules/inflowwind/src/IfW_FlowField.f90
@@ -261,11 +261,11 @@ subroutine IfW_FlowField_GetVelAcc(FF, IStart, Time, PositionXYZ, VelocityUVW, A
cycle
end if
- call Grid4DField_GetVel(FF%Grid4D, Time, Position(:, i), VelocityUVW(:, i), TmpErrStat, TmpErrMsg)
- if (TmpErrStat >= AbortErrLev) then
- call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
- return
- end if
+ call Grid4DField_GetVel(FF%Grid4D, Time, Position(:, i), VelocityUVW(:, i), TmpErrStat, TmpErrMsg)
+ if (TmpErrStat >= AbortErrLev) then
+ call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
+ return
+ end if
end do
case (Point_FieldType)
@@ -1232,34 +1232,32 @@ subroutine GetBoundsT(PosX, DT)
! In distance, X: InputInfo%PosX - p%InitXPosition - TIME*p%MeanWS
TimeShifted = real(Time, ReKi) + (G3D%InitXPosition - PosX)*G3D%InvMWS
+ ! Get position on T grid
+ T_GRID = TimeShifted*G3D%Rate
+
! If field is periodic
if (G3D%Periodic) then
- TimeShifted = MODULO(TimeShifted, G3D%TotalTime)
- ! If TimeShifted is a very small negative number,
- ! modulo returns the incorrect value due to internal rounding errors.
- ! See bug report #471
- if (TimeShifted == G3D%TotalTime) TimeShifted = 0.0_ReKi
+ ! Take modulus of negative grid to get positive value between 0 and NSteps
+ T_GRID = MODULO(T_GRID, real(G3D%NSteps, ReKi))
+ ! For very small negative numbers, the above modulus will return exactly NSteps
+ ! so take modulus again to ensure that T_GRID is less than NSteps
+ T_GRID = MODULO(T_GRID, real(G3D%NSteps, ReKi))
end if
-
- ! Get position on T grid
- T_GRID = TimeShifted*G3D%Rate + 1
-
+
! Calculate bounding grid indices
- IT_LO = floor(T_GRID, IntKi)
- IT_HI = ceiling(T_GRID, IntKi)
+ IT_LO = floor(T_GRID, IntKi) + 1
+ IT_HI = IT_LO + 1
! Position location within interval [0,1]
- DT = T_GRID - aint(T_GRID)
+ DT = 2.0_ReKi*(T_GRID - aint(T_GRID)) - 1.0_ReKi
! Adjust indices and interpolant
if (IT_LO >= 1 .and. IT_HI <= G3D%NSteps) then
! Point is within grid
- DT = 2.0_ReKi*DT - 1.0_ReKi
else if (IT_LO == G3D%NSteps) then
if (G3D%Periodic) then
! Time wraps back to beginning
IT_HI = 1
- DT = 2.0_ReKi*DT - 1.0_ReKi
else if (DT <= GridTol) then
! Within tolerance of last time
IT_HI = IT_LO
@@ -1268,13 +1266,13 @@ subroutine GetBoundsT(PosX, DT)
! Extrapolate
IT_LO = G3D%NSteps - 1
IT_HI = G3D%NSteps
- DT = DT + 1.0_ReKi
end if
else
! Time exceeds array bounds
call SetErrStat(ErrID_Fatal, ' Error: GF wind array was exhausted at '// &
TRIM(Num2LStr(TIME))//' seconds (trying to access data at '// &
- TRIM(Num2LStr(TimeShifted))//' seconds).', &
+ TRIM(Num2LStr(TimeShifted))//' seconds). IT_Lo='//TRIM(Num2LStr(IT_Lo))// &
+ ', IT_HI='//TRIM(Num2LStr(IT_Hi)), &
ErrStat, ErrMsg, RoutineName)
end if
@@ -1529,6 +1527,7 @@ subroutine IfW_Grid3DField_CalcVelAvgProfile(G3D, CalcAccel, ErrStat, ErrMsg)
character(*), parameter :: RoutineName = 'IfW_Grid3DField_CalcVelAvgProfile'
integer(IntKi) :: ErrStat2
character(ErrMsgLen) :: ErrMsg2
+ integer(IntKi) :: it, iz, ic
ErrStat = ErrID_None
ErrMsg = ""
@@ -1543,7 +1542,13 @@ subroutine IfW_Grid3DField_CalcVelAvgProfile(G3D, CalcAccel, ErrStat, ErrMsg)
end if
! Calculate average velocity for each component across grid (Y)
- G3D%VelAvg = sum(G3D%Vel, dim=2)/G3D%NYGrids
+ do it = 1, G3D%NSteps
+ do iz = 1, G3D%NZGrids
+ do ic = 1, G3D%NComp
+ G3D%VelAvg(ic,iz,it) = sum(G3D%Vel(ic,:,iz,it))/real(G3D%NYGrids, SiKi)
+ end do
+ end do
+ end do
! If acceleration calculation not requested, return
if (.not. CalcAccel) return
@@ -1556,9 +1561,15 @@ subroutine IfW_Grid3DField_CalcVelAvgProfile(G3D, CalcAccel, ErrStat, ErrMsg)
if (ErrStat >= AbortErrLev) return
G3D%AccAvg = 0.0_SiKi
end if
-
+
! Calculate average acceleration for each component across grid (Y)
- G3D%AccAvg = sum(G3D%Acc, dim=2)/G3D%NYGrids
+ do it = 1, G3D%NSteps
+ do iz = 1, G3D%NZGrids
+ do ic = 1, G3D%NComp
+ G3D%AccAvg(ic,iz,it) = sum(G3D%Acc(ic,:,iz,it))/real(G3D%NYGrids, SiKi)
+ end do
+ end do
+ end do
end subroutine
@@ -1589,7 +1600,7 @@ subroutine Grid4DField_GetVel(G4D, Time, Position, Velocity, ErrStat, ErrMsg)
!----------------------------------------------------------------------------
do i = 1, 3
- tmp = (Position(i) - G4D%pZero(i))/G4D%delta(i)
+ tmp = (Position(i) - G4D%pZero(i))/real(G4D%delta(i),Reki)
Indx_Lo(i) = INT(tmp) + 1 ! convert REAL to INTEGER, then add one since our grid indices start at 1, not 0
xi(i) = 2.0_ReKi*(tmp - aint(tmp)) - 1.0_ReKi ! convert to value between -1 and 1
end do
diff --git a/modules/inflowwind/src/IfW_FlowField.txt b/modules/inflowwind/src/IfW_FlowField.txt
index cb890684f4..dafaa1871f 100644
--- a/modules/inflowwind/src/IfW_FlowField.txt
+++ b/modules/inflowwind/src/IfW_FlowField.txt
@@ -95,10 +95,10 @@ typedef ^ ^ LOGICAL BoxExceedWarn
#----------------------------------------------------------------------------------------------------------------------------------
typedef ^ Grid4DFieldType IntKi n 4 - - "number of evenly-spaced grid points in the x, y, z, and t directions" -
-typedef ^ ^ ReKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s"
+typedef ^ ^ DbKi delta 4 - - "size between 2 consecutive grid points in each grid direction" "m,m,m,s"
typedef ^ ^ ReKi pZero 3 - - "fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:))" "m"
typedef ^ ^ SiKi Vel ::::: - - "this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt]" -
-typedef ^ ^ ReKi TimeStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s
+typedef ^ ^ DbKi TimeStart - - - "this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1))" s
typedef ^ ^ ReKi RefHeight - - - "reference height; used to center the wind" meters
#----------------------------------------------------------------------------------------------------------------------------------
diff --git a/modules/inflowwind/src/IfW_FlowField_Types.f90 b/modules/inflowwind/src/IfW_FlowField_Types.f90
index c8a8055785..9ae7a192f6 100644
--- a/modules/inflowwind/src/IfW_FlowField_Types.f90
+++ b/modules/inflowwind/src/IfW_FlowField_Types.f90
@@ -130,10 +130,10 @@ MODULE IfW_FlowField_Types
! ========= Grid4DFieldType =======
TYPE, PUBLIC :: Grid4DFieldType
INTEGER(IntKi) , DIMENSION(1:4) :: n !< number of evenly-spaced grid points in the x, y, z, and t directions [-]
- REAL(ReKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s]
+ REAL(DbKi) , DIMENSION(1:4) :: delta !< size between 2 consecutive grid points in each grid direction [m,m,m,s]
REAL(ReKi) , DIMENSION(1:3) :: pZero !< fixed position of the XYZ grid (i.e., XYZ coordinates of m%V(:,1,1,1,:)) [m]
REAL(SiKi) , DIMENSION(:,:,:,:,:), ALLOCATABLE :: Vel !< this is the 4-d velocity field for each wind component [{uvw},nx,ny,nz,nt] [-]
- REAL(ReKi) :: TimeStart !< this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1)) [s]
+ REAL(DbKi) :: TimeStart !< this is the time where the first time grid in m%V starts (i.e, the time associated with m%V(:,:,:,:,1)) [s]
REAL(ReKi) :: RefHeight !< reference height; used to center the wind [meters]
END TYPE Grid4DFieldType
! =======================
@@ -2390,14 +2390,14 @@ SUBROUTINE IfW_FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata
Db_BufSz = 0
Int_BufSz = 0
Int_BufSz = Int_BufSz + SIZE(InData%n) ! n
- Re_BufSz = Re_BufSz + SIZE(InData%delta) ! delta
+ Db_BufSz = Db_BufSz + SIZE(InData%delta) ! delta
Re_BufSz = Re_BufSz + SIZE(InData%pZero) ! pZero
Int_BufSz = Int_BufSz + 1 ! Vel allocated yes/no
IF ( ALLOCATED(InData%Vel) ) THEN
Int_BufSz = Int_BufSz + 2*5 ! Vel upper/lower bounds for each dimension
Re_BufSz = Re_BufSz + SIZE(InData%Vel) ! Vel
END IF
- Re_BufSz = Re_BufSz + 1 ! TimeStart
+ Db_BufSz = Db_BufSz + 1 ! TimeStart
Re_BufSz = Re_BufSz + 1 ! RefHeight
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
@@ -2431,8 +2431,8 @@ SUBROUTINE IfW_FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata
Int_Xferred = Int_Xferred + 1
END DO
DO i1 = LBOUND(InData%delta,1), UBOUND(InData%delta,1)
- ReKiBuf(Re_Xferred) = InData%delta(i1)
- Re_Xferred = Re_Xferred + 1
+ DbKiBuf(Db_Xferred) = InData%delta(i1)
+ Db_Xferred = Db_Xferred + 1
END DO
DO i1 = LBOUND(InData%pZero,1), UBOUND(InData%pZero,1)
ReKiBuf(Re_Xferred) = InData%pZero(i1)
@@ -2473,8 +2473,8 @@ SUBROUTINE IfW_FlowField_PackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Indata
END DO
END DO
END IF
- ReKiBuf(Re_Xferred) = InData%TimeStart
- Re_Xferred = Re_Xferred + 1
+ DbKiBuf(Db_Xferred) = InData%TimeStart
+ Db_Xferred = Db_Xferred + 1
ReKiBuf(Re_Xferred) = InData%RefHeight
Re_Xferred = Re_Xferred + 1
END SUBROUTINE IfW_FlowField_PackGrid4DFieldType
@@ -2519,8 +2519,8 @@ SUBROUTINE IfW_FlowField_UnPackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outd
i1_l = LBOUND(OutData%delta,1)
i1_u = UBOUND(OutData%delta,1)
DO i1 = LBOUND(OutData%delta,1), UBOUND(OutData%delta,1)
- OutData%delta(i1) = ReKiBuf(Re_Xferred)
- Re_Xferred = Re_Xferred + 1
+ OutData%delta(i1) = DbKiBuf(Db_Xferred)
+ Db_Xferred = Db_Xferred + 1
END DO
i1_l = LBOUND(OutData%pZero,1)
i1_u = UBOUND(OutData%pZero,1)
@@ -2566,8 +2566,8 @@ SUBROUTINE IfW_FlowField_UnPackGrid4DFieldType( ReKiBuf, DbKiBuf, IntKiBuf, Outd
END DO
END DO
END IF
- OutData%TimeStart = ReKiBuf(Re_Xferred)
- Re_Xferred = Re_Xferred + 1
+ OutData%TimeStart = DbKiBuf(Db_Xferred)
+ Db_Xferred = Db_Xferred + 1
OutData%RefHeight = ReKiBuf(Re_Xferred)
Re_Xferred = Re_Xferred + 1
END SUBROUTINE IfW_FlowField_UnPackGrid4DFieldType
diff --git a/modules/inflowwind/src/InflowWind.f90 b/modules/inflowwind/src/InflowWind.f90
index 46bf3325d9..103ddb948b 100644
--- a/modules/inflowwind/src/InflowWind.f90
+++ b/modules/inflowwind/src/InflowWind.f90
@@ -128,8 +128,6 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
Type(User_InitInputType) :: User_InitInput
Type(Grid4D_InitInputType) :: Grid4D_InitInput
Type(Points_InitInputType) :: Points_InitInput
-
- Type(WindFileDat) :: FileDat
! TYPE(InflowWind_IO_InitInputType) :: FlowField_InitData !< initialization info
@@ -301,7 +299,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
Steady_InitInput%PLExp = InputFileData%Steady_PLexp
p%FlowField%FieldType = Uniform_FieldType
- call IfW_SteadyWind_Init(Steady_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg)
+ call IfW_SteadyWind_Init(Steady_InitInput, SumFileUnit, p%FlowField%Uniform, InitOutData%WindFileInfo, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
call Cleanup()
@@ -321,7 +319,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
Uniform_InitInput%PassedFileData = InitInp%WindType2Data
p%FlowField%FieldType = Uniform_FieldType
- call IfW_UniformWind_Init(Uniform_InitInput, SumFileUnit, p%FlowField%Uniform, FileDat, TmpErrStat, TmpErrMsg)
+ call IfW_UniformWind_Init(Uniform_InitInput, SumFileUnit, p%FlowField%Uniform, InitOutData%WindFileInfo, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
call Cleanup()
@@ -336,7 +334,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
TurbSim_InitInput%WindFileName = InputFileData%TSFF_FileName
p%FlowField%FieldType = Grid3D_FieldType
- call IfW_TurbSim_Init(TurbSim_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg)
+ call IfW_TurbSim_Init(TurbSim_InitInput, SumFileUnit, p%FlowField%Grid3D, InitOutData%WindFileInfo, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
call Cleanup()
@@ -362,7 +360,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
Bladed_InitInput%NativeBladedFmt = .false.
p%FlowField%FieldType = Grid3D_FieldType
- call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg)
+ call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, InitOutData%WindFileInfo, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
call Cleanup()
@@ -371,7 +369,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
! Set reference position for wind rotation
p%FlowField%RefPosition = [0.0_ReKi, 0.0_ReKi, p%FlowField%Grid3D%RefHeight]
-
+
case (BladedFF_Shr_WindNumber)
Bladed_InitInput%WindType = BladedFF_Shr_WindNumber
@@ -381,7 +379,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
Bladed_InitInput%NativeBladedFmt = .true.
p%FlowField%FieldType = Grid3D_FieldType
- call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg)
+ call IfW_Bladed_Init(Bladed_InitInput, SumFileUnit, Bladed_InitOutput, p%FlowField%Grid3D, InitOutData%WindFileInfo, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
call Cleanup()
@@ -417,7 +415,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
HAWC_InitInput%G3D%XOffset = InputFileData%FF%XOffset
p%FlowField%FieldType = Grid3D_FieldType
- call IfW_HAWC_Init(HAWC_InitInput, SumFileUnit, p%FlowField%Grid3D, FileDat, TmpErrStat, TmpErrMsg)
+ call IfW_HAWC_Init(HAWC_InitInput, SumFileUnit, p%FlowField%Grid3D, InitOutData%WindFileInfo, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
call Cleanup()
@@ -430,7 +428,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
case (User_WindNumber)
p%FlowField%FieldType = User_FieldType
- call IfW_User_Init(User_InitInput, SumFileUnit, p%FlowField%User, FileDat, TmpErrStat, TmpErrMsg)
+ call IfW_User_Init(User_InitInput, SumFileUnit, p%FlowField%User, InitOutData%WindFileInfo, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
call Cleanup()
@@ -518,7 +516,7 @@ SUBROUTINE InflowWind_Init( InitInp, InputGuess, p, ContStates, DiscStates, Cons
end if
! Calculate field average if box is allowed to be exceeded
- if (p%FlowField%Grid3D%BoxExceedAllowF .and. p%FlowField%Grid3D%BoxExceedAllowIdx > 0) then
+ if (p%FlowField%Grid3D%BoxExceedAllowF) then
call IfW_Grid3DField_CalcVelAvgProfile(p%FlowField%Grid3D, p%FlowField%AccFieldValid, TmpErrStat, TmpErrMsg)
call SetErrStat(TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) return
diff --git a/modules/inflowwind/src/InflowWind_Driver.f90 b/modules/inflowwind/src/InflowWind_Driver.f90
index 77beb83a58..a2c83478b9 100644
--- a/modules/inflowwind/src/InflowWind_Driver.f90
+++ b/modules/inflowwind/src/InflowWind_Driver.f90
@@ -734,8 +734,7 @@ PROGRAM InflowWind_Driver
IF ( IfWDriver_Verbose >= 5_IntKi ) CALL WrScr(NewLine//'Calling InflowWind_CalcOutput...'//NewLine)
- DO ITime = 0, MAX( Settings%NumTimeSteps, 1_IntKi )
-
+ DO ITime = 0, MAX( Settings%NumTimeSteps, 0_IntKi )
TimeNow = Settings%TStart + Settings%DT*(ITime)
IF ( SettingsFlags%WindGrid ) THEN
diff --git a/modules/inflowwind/src/InflowWind_Driver_Subs.f90 b/modules/inflowwind/src/InflowWind_Driver_Subs.f90
index d7033445b2..186b3435df 100644
--- a/modules/inflowwind/src/InflowWind_Driver_Subs.f90
+++ b/modules/inflowwind/src/InflowWind_Driver_Subs.f90
@@ -1413,8 +1413,8 @@ SUBROUTINE UpdateSettingsWithCL( DvrFlags, DvrSettings, CLFlags, CLSettings, DVR
DvrFlags%NumTimeStepsDefault = .FALSE.
ENDIF
- ! Make sure there is at least one timestep
- DvrSettings%NumTimeSteps = MAX(DvrSettings%NumTimeSteps,1_IntKi)
+ ! Make sure there is at least one timestep (start at index 0)
+ DvrSettings%NumTimeSteps = MAX(DvrSettings%NumTimeSteps,0_IntKi)
!--------------------------------------------
diff --git a/modules/inflowwind/src/InflowWind_IO.f90 b/modules/inflowwind/src/InflowWind_IO.f90
index 122d8a5cec..e1b0f64547 100644
--- a/modules/inflowwind/src/InflowWind_IO.f90
+++ b/modules/inflowwind/src/InflowWind_IO.f90
@@ -1031,7 +1031,7 @@ subroutine IfW_Grid4D_Init(InitInp, G4D, ErrStat, ErrMsg)
! Initialize field from inputs
G4D%n = InitInp%n
- G4D%delta = InitInp%delta
+ G4D%delta = real(InitInp%delta, DbKi)
G4D%pZero = InitInp%pZero
G4D%TimeStart = 0.0_ReKi
G4D%RefHeight = InitInp%pZero(3) + (InitInp%n(3)/2) * InitInp%delta(3)
@@ -2540,8 +2540,8 @@ subroutine Grid3D_ScaleTurbulence(InitInp, Vel, ScaleFactors, ErrStat, ErrMsg)
iy = (ny + 1)/2 ! integer division
! compute the actual sigma at the point specified by (iy,iz). (This sigma should be close to 1.)
- vSum = sum(Vel(:, iy, iz, :), dim=2)
- vSum2 = sum(Vel(:, iy, iz, :)**2, dim=2)
+ vSum = sum(real(Vel(:, iy, iz, :),R8Ki), dim=2)
+ vSum2 = sum(real(Vel(:, iy, iz, :),R8Ki)**2, dim=2)
vMean = vSum/nt
ActualSigma = real(SQRT(ABS((vSum2/nt) - vMean**2)), ReKi)
diff --git a/modules/inflowwind/src/InflowWind_Subs.f90 b/modules/inflowwind/src/InflowWind_Subs.f90
index ed69082636..de910b24c8 100644
--- a/modules/inflowwind/src/InflowWind_Subs.f90
+++ b/modules/inflowwind/src/InflowWind_Subs.f90
@@ -1733,7 +1733,7 @@ SUBROUTINE InflowWind_GetHubValues( Time, InputData, p, x, xd, z, OtherStates, m
IMPLICIT NONE
- CHARACTER(*), PARAMETER :: RoutineName="InflowWind_GetSpatialAverage"
+ CHARACTER(*), PARAMETER :: RoutineName="InflowWind_GetHubValues"
! Inputs / Outputs
diff --git a/modules/inflowwind/src/Lidar.f90 b/modules/inflowwind/src/Lidar.f90
index ec35b2a3f7..9a83c4ce9b 100644
--- a/modules/inflowwind/src/Lidar.f90
+++ b/modules/inflowwind/src/Lidar.f90
@@ -118,7 +118,7 @@ SUBROUTINE Lidar_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init
RETURN
ENDIF
- CALL AllocAry(p%lidar%MsrPosition , 3, p%lidar%NumBeam, 'Array for measurement coordinates', TmpErrStat, TmpErrMsg )
+ CALL AllocAry(p%lidar%MsrPosition , 3, max(1,p%lidar%NumBeam), 'Array for measurement coordinates', TmpErrStat, TmpErrMsg )
CALL SetErrStat( TmpErrStat, TmpErrMsg, ErrStat, ErrMsg, RoutineName)
IF ( ErrStat>= AbortErrLev ) RETURN
@@ -362,7 +362,8 @@ SUBROUTINE Lidar_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMs
MeasurementCurrentStep = INT(t / p%lidar%MeasurementInterval)
IF ( (p%lidar%MeasurementInterval * MeasurementCurrentStep) /= t ) THEN
- Output%VelocityUVW(:,1) = 0
+!This isn't returned, so don't set it.
+! Output%VelocityUVW(:,1) = 0
RETURN
ENDIF
diff --git a/modules/map/src/lineroutines.c b/modules/map/src/lineroutines.c
index 30fad7a27e..ba89c7b5bd 100644
--- a/modules/map/src/lineroutines.c
+++ b/modules/map/src/lineroutines.c
@@ -667,7 +667,7 @@ MAP_ERROR_CODE solve_linear_spring_cable(Line* line, char* map_msg, MAP_ERROR_CO
};
*(line->H.value) = sqrt(force.x*force.x + force.y*force.y);
- *(line->V.value) = fabs(force.z);
+ *(line->V.value) = -force.z; /* vertical force can be positive or negative. Important for systems with the anchor point above the fairlead connection */
return MAP_SAFE;
};
diff --git a/modules/moordyn/src/MoorDyn.f90 b/modules/moordyn/src/MoorDyn.f90
index d378015b22..3c6919ca45 100644
--- a/modules/moordyn/src/MoorDyn.f90
+++ b/modules/moordyn/src/MoorDyn.f90
@@ -194,6 +194,7 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er
p%mu_kA = 0.0_DbKi
p%mc = 1.0_DbKi
p%cv = 200.0_DbKi
+ p%VisMeshes = InitInp%VisMeshes ! Visualization meshes requested by glue code
DepthValue = "" ! Start off as empty string, to only be filled if MD setting is specified (otherwise InitInp%WtrDepth is used)
! DepthValue and InitInp%WtrDepth are processed later by setupBathymetry.
WaterKinValue = ""
@@ -931,8 +932,8 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er
CALL Body_AddRod(m%GroundBody, l, tempArray) ! add rod l to Ground body
- else if ((let1 == "PINNED") .or. (let1 == "PIN")) then
- m%RodList(l)%typeNum = 1
+ else if ((let1 == "PINNED") .or. (let1 == "PIN")) then
+ m%RodList(l)%typeNum = 1
CALL Body_AddRod(m%GroundBody, l, tempArray) ! add rod l to Ground body
p%nFreeRods=p%nFreeRods+1 ! add this pinned rod to the free list because it is half free
@@ -2212,6 +2213,19 @@ SUBROUTINE MD_Init(InitInp, u, p, x, xd, z, other, y, m, DTcoupling, InitOut, Er
! TODO: add feature for automatic water depth increase based on max anchor depth!
+
+ !--------------------------------------------------
+ ! initialize line visualization meshes if needed
+ if (p%VisMeshes) then
+ if (p%NLines > 0) then
+ call VisLinesMesh_Init(p,m,y,ErrStat2,ErrMsg2); if(Failed()) return
+ endif
+ if (p%NRods > 0) then
+ call VisRodsMesh_Init(p,m,y,ErrStat2,ErrMsg2); if(Failed()) return
+ endif
+ endif
+
+
CONTAINS
@@ -2257,12 +2271,12 @@ SUBROUTINE CheckError(ErrID,Msg)
IF ( ErrStat >= AbortErrLev ) THEN
- IF (ALLOCATED(m%CpldPointIs )) DEALLOCATE(m%CpldPointIs )
- IF (ALLOCATED(m%FreePointIs )) DEALLOCATE(m%FreePointIs )
+ IF (ALLOCATED(m%CpldPointIs )) DEALLOCATE(m%CpldPointIs )
+ IF (ALLOCATED(m%FreePointIs )) DEALLOCATE(m%FreePointIs )
IF (ALLOCATED(m%LineStateIs1 )) DEALLOCATE(m%LineStateIs1 )
IF (ALLOCATED(m%LineStateIsN )) DEALLOCATE(m%LineStateIsN )
- IF (ALLOCATED(m%PointStateIs1 )) DEALLOCATE(m%PointStateIs1 )
- IF (ALLOCATED(m%PointStateIsN )) DEALLOCATE(m%PointStateIsN )
+ IF (ALLOCATED(m%PointStateIs1 )) DEALLOCATE(m%PointStateIs1 )
+ IF (ALLOCATED(m%PointStateIsN )) DEALLOCATE(m%PointStateIsN )
IF (ALLOCATED(x%states )) DEALLOCATE(x%states )
IF (ALLOCATED(FairTensIC )) DEALLOCATE(FairTensIC )
@@ -2613,6 +2627,20 @@ SUBROUTINE MD_CalcOutput( t, u, p, x, xd, z, other, y, m, ErrStat, ErrMsg )
! IF ( ErrStat >= AbortErrLev ) RETURN
+ !--------------------------------------------------
+ ! update line visualization meshes if needed
+ if (p%VisMeshes) then
+ if (p%NLines > 0) then
+ call VisLinesMesh_Update(p,m,y,ErrStat2,ErrMsg2)
+ call CheckError(ErrStat2, ErrMsg2)
+ if ( ErrStat >= AbortErrLev ) return
+ endif
+ if (p%NRods > 0) then
+ call VisRodsMesh_Update(p,m,y,ErrStat2,ErrMsg2)
+ call CheckError(ErrStat2, ErrMsg2)
+ if ( ErrStat >= AbortErrLev ) return
+ endif
+ endif
CONTAINS
diff --git a/modules/moordyn/src/MoorDyn_Line.f90 b/modules/moordyn/src/MoorDyn_Line.f90
index 3235c4e738..21cd2d71ef 100644
--- a/modules/moordyn/src/MoorDyn_Line.f90
+++ b/modules/moordyn/src/MoorDyn_Line.f90
@@ -39,7 +39,8 @@ MODULE MoorDyn_Line
PUBLIC :: Line_GetEndStuff
PUBLIC :: Line_GetEndSegmentInfo
PUBLIC :: Line_SetEndOrientation
-
+ public :: VisLinesMesh_Init
+ public :: VisLinesMesh_Update
CONTAINS
@@ -1661,5 +1662,94 @@ SUBROUTINE Line_SetEndOrientation(Line, qin, topOfLine, rodEndB)
END SUBROUTINE Line_SetEndOrientation
!--------------------------------------------------------------
+ subroutine VisLinesMesh_Init(p,m,y,ErrStat,ErrMsg)
+ type(MD_ParameterType), intent(in ) :: p
+ type(MD_MiscVarType), intent(in ) :: m
+ type(MD_OutputType), intent(inout) :: y
+ integer(IntKi), intent( out) :: ErrStat
+ character(*), intent( out) :: ErrMsg
+ integer(IntKi) :: ErrStat2
+ character(ErrMsgLen) :: ErrMsg2
+ integer(IntKi) :: i,l
+ character(*), parameter :: RoutineName = 'VisLinesMesh_Init'
+
+ ErrStat = ErrID_None
+ ErrMsg = ''
+
+ ! allocate line2 mesh for all lines
+ allocate (y%VisLinesMesh(p%NLines), STAT=ErrStat2); if (Failed0('visualization mesh for lines')) return
+
+ ! Initialize mesh for each line (line nodes start at 0 index, so N+1 total nodes)
+ do l=1,p%NLines
+ CALL MeshCreate( BlankMesh = y%VisLinesMesh(l), &
+ NNodes = m%LineList(l)%N+1, &
+ IOS = COMPONENT_OUTPUT, &
+ TranslationDisp = .true., &
+ ErrStat=ErrStat2, ErrMess=ErrMsg2)
+ if (Failed()) return
+
+ ! Internal nodes (line nodes start at 0 index)
+ do i = 0,m%LineList(l)%N
+ call MeshPositionNode ( y%VisLinesMesh(l), i+1, real(m%LineList(l)%r(:,I),ReKi), ErrStat2, ErrMsg2 )
+ if (Failed()) return
+ enddo
+
+ ! make elements (line nodes start at 0 index, so N+1 total nodes)
+ do i = 2,m%LineList(l)%N+1
+ call MeshConstructElement ( Mesh = y%VisLinesMesh(l) &
+ , Xelement = ELEMENT_LINE2 &
+ , P1 = i-1 & ! node1 number
+ , P2 = i & ! node2 number
+ , ErrStat = ErrStat2 &
+ , ErrMess = ErrMsg2 )
+ if (Failed()) return
+ enddo
+
+ ! Commit mesh
+ call MeshCommit ( y%VisLinesMesh(l), ErrStat2, ErrMsg2 )
+ if (Failed()) return
+ enddo
+ contains
+ logical function Failed()
+ CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName )
+ Failed = ErrStat >= AbortErrLev
+ end function Failed
+
+ ! check for failed where /= 0 is fatal
+ logical function Failed0(txt)
+ character(*), intent(in) :: txt
+ if (errStat /= 0) then
+ ErrStat2 = ErrID_Fatal
+ ErrMsg2 = "Could not allocate "//trim(txt)
+ call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ endif
+ Failed0 = ErrStat >= AbortErrLev
+ end function Failed0
+ end subroutine VisLinesMesh_Init
+
+
+
+ subroutine VisLinesMesh_Update(p,m,y,ErrStat,ErrMsg)
+ type(MD_ParameterType), intent(in ) :: p
+ type(MD_MiscVarType), intent(in ) :: m
+ type(MD_OutputType), intent(inout) :: y
+ integer(IntKi), intent( out) :: ErrStat
+ character(*), intent( out) :: ErrMsg
+ integer(IntKi) :: i,l
+ character(*), parameter :: RoutineName = 'VisLinesMesh_Update'
+
+ ErrStat = ErrID_None
+ ErrMsg = ''
+
+ ! Initialize mesh for each line (line nodes start at 0 index, so N+1 total nodes)
+ do l=1,p%NLines
+ ! Update node positions nodes (line nodes start at 0 index)
+ do i = 0,m%LineList(l)%N
+ y%VisLinesMesh(l)%TranslationDisp(:,i+1) = real(m%LineList(l)%r(:,I),ReKi) - y%VisLinesMesh(l)%Position(:,i+1)
+ enddo
+ enddo
+ end subroutine VisLinesMesh_Update
+
+
END MODULE MoorDyn_Line
diff --git a/modules/moordyn/src/MoorDyn_Registry.txt b/modules/moordyn/src/MoorDyn_Registry.txt
index 60a78f2676..e221bb7bfc 100644
--- a/modules/moordyn/src/MoorDyn_Registry.txt
+++ b/modules/moordyn/src/MoorDyn_Registry.txt
@@ -34,6 +34,7 @@ typedef ^ ^ FileInfoType PassedPrimaryInputData
typedef ^ ^ LOGICAL Echo - "" - "echo parameter - do we want to echo the header line describing the input file?"
typedef ^ ^ CHARACTER(ChanLen) OutList {:} "" - "string containing list of output channels requested in input file"
typedef ^ ^ Logical Linearize - .FALSE. - "Flag that tells this module if the glue code wants to linearize." -
+typedef ^ ^ Logical VisMeshes - .FALSE. - "Glue code requesting visualization meshes" -
#typedef ^ ^ DbKi UGrid {:}{:}{:} - - "water velocities time series at each grid point" -
#typedef ^ ^ DbKi UdGrid {:}{:}{:} - - "water accelerations time series at each grid point" -
@@ -282,6 +283,8 @@ typedef ^ ^ IntKi OType -
typedef ^ ^ IntKi NodeID - - - "node number if OType=0. 0=anchor, -1=N=Fairlead"
typedef ^ ^ IntKi ObjID - - - "number of Point or Line object"
+## ============================== Visualization data storage for diameter ============================================================================================================================
+typedef ^ VisDiam SiKi Diam {:} - - "Diameter for visualization" -
## ============================== Define Initialization outputs here: ================================================================================================================================
typedef ^ InitOutputType CHARACTER(ChanLen) writeOutputHdr {:} "" - "first line output file contents: output variable names"
@@ -422,6 +425,8 @@ typedef ^ ^ R8Ki dx {:}
typedef ^ ^ Integer Jac_ny - - - "number of outputs in jacobian matrix" -
typedef ^ ^ Integer Jac_nx - - - "number of continuous states in jacobian matrix" -
typedef ^ ^ Integer dxIdx_map2_xStateIdx {:} - - "Mapping array from index of dX array to corresponding state index" -
+typedef ^ ^ Logical VisMeshes - - - "Using visualization meshes as requested by glue code" -
+typedef ^ ^ VisDiam VisRodsDiam {:} - - "Diameters for visualization of rods" -
# ============================== Inputs ============================================================================================================================================
@@ -439,3 +444,7 @@ typedef ^ OutputType MeshType CoupledLoads {:}
typedef ^ ^ ReKi WriteOutput {:} - - "output vector returned to glue code" ""
# should CoupledLoads be an array?
#typedef ^ ^ DbKi rAll {:}{:} - - "Mesh of all point positions: bodies, rods, points, line internal nodes" -
+typedef ^ ^ MeshType VisLinesMesh {:} - - "Line2 mesh for visualizing mooring lines" -
+typedef ^ ^ MeshType VisRodsMesh {:} - - "Line2 mesh for visualizing mooring rods" -
+typedef ^ ^ MeshType VisBodiesMesh {:} - - "Point mesh for visualizing mooring bodies" -
+typedef ^ ^ MeshType VisAnchsMesh {:} - - "Point mesh for visualizing mooring anchors" -
diff --git a/modules/moordyn/src/MoorDyn_Rod.f90 b/modules/moordyn/src/MoorDyn_Rod.f90
index dca892ffff..f7f25e4d93 100644
--- a/modules/moordyn/src/MoorDyn_Rod.f90
+++ b/modules/moordyn/src/MoorDyn_Rod.f90
@@ -42,9 +42,11 @@ MODULE MoorDyn_Rod
PUBLIC :: Rod_GetNetForceAndMass
PUBLIC :: Rod_AddLine
PUBLIC :: Rod_RemoveLine
+ public :: VisRodsMesh_Init
+ public :: VisRodsMesh_Update
+
-
CONTAINS
@@ -1190,5 +1192,102 @@ END SUBROUTINE Rod_RemoveLine
+ subroutine VisRodsMesh_Init(p,m,y,ErrStat,ErrMsg)
+ type(MD_ParameterType), intent(inout) :: p
+ type(MD_MiscVarType), intent(in ) :: m
+ type(MD_OutputType), intent(inout) :: y
+ integer(IntKi), intent( out) :: ErrStat
+ character(*), intent( out) :: ErrMsg
+ integer(IntKi) :: ErrStat2
+ character(ErrMsgLen) :: ErrMsg2
+ integer(IntKi) :: i,l
+ character(*), parameter :: RoutineName = 'VisRodsMesh_Init'
+
+ ErrStat = ErrID_None
+ ErrMsg = ''
+
+ ! allocate line2 mesh for all lines
+ allocate (y%VisRodsMesh(p%NRods), STAT=ErrStat2); if (Failed0('visualization mesh for lines')) return
+ allocate (p%VisRodsDiam(p%NRods), STAT=ErrStat2); if (Failed0('visualization mesh for lines')) return
+
+ ! Initialize mesh for each line (line nodes start at 0 index, so N+1 total nodes)
+ do l=1,p%NRods
+ CALL MeshCreate( BlankMesh = y%VisRodsMesh(l), &
+ NNodes = m%RodList(l)%N+1, &
+ IOS = COMPONENT_OUTPUT, &
+ TranslationDisp = .true., &
+ Orientation = .true., &
+ ErrStat=ErrStat2, ErrMess=ErrMsg2)
+ if (Failed()) return
+
+ ! Internal nodes (line nodes start at 0 index)
+ do i = 0,m%RodList(l)%N
+ call MeshPositionNode ( y%VisRodsMesh(l), i+1, real(m%RodList(l)%r(:,I),ReKi), ErrStat2, ErrMsg2, Orient=real(m%RodList(l)%OrMat,R8Ki))
+ if (Failed()) return
+ enddo
+
+ ! make elements (line nodes start at 0 index, so N+1 total nodes)
+ do i = 2,m%RodList(l)%N+1
+ call MeshConstructElement ( Mesh = y%VisRodsMesh(l) &
+ , Xelement = ELEMENT_LINE2 &
+ , P1 = i-1 & ! node1 number
+ , P2 = i & ! node2 number
+ , ErrStat = ErrStat2 &
+ , ErrMess = ErrMsg2 )
+ if (Failed()) return
+ enddo
+
+ ! Commit mesh
+ call MeshCommit ( y%VisRodsMesh(l), ErrStat2, ErrMsg2 )
+ if (Failed()) return
+
+ ! Set rod diameter for visualization
+ call AllocAry(p%VisRodsDiam(l)%Diam,m%RodList(l)%N+1,'',ErrStat2,ErrMsg2)
+ if (Failed()) return
+ p%VisRodsDiam(l)%Diam=real(m%RodTypeList(m%RodList(l)%PropsIdNum)%d,SiKi)
+ enddo
+ contains
+ logical function Failed()
+ CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName )
+ Failed = ErrStat >= AbortErrLev
+ end function Failed
+
+ ! check for failed where /= 0 is fatal
+ logical function Failed0(txt)
+ character(*), intent(in) :: txt
+ if (errStat /= 0) then
+ ErrStat2 = ErrID_Fatal
+ ErrMsg2 = "Could not allocate "//trim(txt)
+ call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ endif
+ Failed0 = ErrStat >= AbortErrLev
+ end function Failed0
+ end subroutine VisRodsMesh_Init
+
+
+
+ subroutine VisRodsMesh_Update(p,m,y,ErrStat,ErrMsg)
+ type(MD_ParameterType), intent(in ) :: p
+ type(MD_MiscVarType), intent(in ) :: m
+ type(MD_OutputType), intent(inout) :: y
+ integer(IntKi), intent( out) :: ErrStat
+ character(*), intent( out) :: ErrMsg
+ integer(IntKi) :: i,l
+ character(*), parameter :: RoutineName = 'VisRodsMesh_Update'
+
+ ErrStat = ErrID_None
+ ErrMsg = ''
+
+ do l=1,p%NRods
+ ! Update rod positions/orientations
+ do i = 0,m%RodList(l)%N
+ y%VisRodsMesh(l)%TranslationDisp(:,i+1) = real(m%RodList(l)%r(:,I),ReKi) - y%VisRodsMesh(l)%Position(:,i+1)
+ y%VisRodsMesh(l)%Orientation(:,:,i+1) = real(m%RodList(l)%OrMat,R8Ki)
+ enddo
+ enddo
+ end subroutine VisRodsMesh_Update
+
+
+
END MODULE MoorDyn_Rod
diff --git a/modules/moordyn/src/MoorDyn_Types.f90 b/modules/moordyn/src/MoorDyn_Types.f90
index a786b07300..6d00b2a689 100644
--- a/modules/moordyn/src/MoorDyn_Types.f90
+++ b/modules/moordyn/src/MoorDyn_Types.f90
@@ -57,6 +57,7 @@ MODULE MoorDyn_Types
LOGICAL :: Echo !< echo parameter - do we want to echo the header line describing the input file? [-]
CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< string containing list of output channels requested in input file [-]
LOGICAL :: Linearize = .FALSE. !< Flag that tells this module if the glue code wants to linearize. [-]
+ LOGICAL :: VisMeshes = .FALSE. !< Glue code requesting visualization meshes [-]
REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveVel !< [-]
REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: WaveAcc !< [-]
REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: WavePDyn !< [-]
@@ -306,6 +307,11 @@ MODULE MoorDyn_Types
INTEGER(IntKi) :: ObjID !< number of Point or Line object [-]
END TYPE MD_OutParmType
! =======================
+! ========= VisDiam =======
+ TYPE, PUBLIC :: VisDiam
+ REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: Diam !< Diameter for visualization [-]
+ END TYPE VisDiam
+! =======================
! ========= MD_InitOutputType =======
TYPE, PUBLIC :: MD_InitOutputType
CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: writeOutputHdr !< first line output file contents: output variable names [-]
@@ -451,6 +457,8 @@ MODULE MoorDyn_Types
INTEGER(IntKi) :: Jac_ny !< number of outputs in jacobian matrix [-]
INTEGER(IntKi) :: Jac_nx !< number of continuous states in jacobian matrix [-]
INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: dxIdx_map2_xStateIdx !< Mapping array from index of dX array to corresponding state index [-]
+ LOGICAL :: VisMeshes !< Using visualization meshes as requested by glue code [-]
+ TYPE(VisDiam) , DIMENSION(:), ALLOCATABLE :: VisRodsDiam !< Diameters for visualization of rods [-]
END TYPE MD_ParameterType
! =======================
! ========= MD_InputType =======
@@ -464,6 +472,10 @@ MODULE MoorDyn_Types
TYPE, PUBLIC :: MD_OutputType
TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: CoupledLoads !< array of point meshes for mooring reaction forces (and moments) at coupling points [[N]]
REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< output vector returned to glue code []
+ TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: VisLinesMesh !< Line2 mesh for visualizing mooring lines [-]
+ TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: VisRodsMesh !< Line2 mesh for visualizing mooring rods [-]
+ TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: VisBodiesMesh !< Point mesh for visualizing mooring bodies [-]
+ TYPE(MeshType) , DIMENSION(:), ALLOCATABLE :: VisAnchsMesh !< Point mesh for visualizing mooring anchors [-]
END TYPE MD_OutputType
! =======================
CONTAINS
@@ -700,6 +712,7 @@ SUBROUTINE MD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrSt
DstInitInputData%OutList = SrcInitInputData%OutList
ENDIF
DstInitInputData%Linearize = SrcInitInputData%Linearize
+ DstInitInputData%VisMeshes = SrcInitInputData%VisMeshes
IF (ALLOCATED(SrcInitInputData%WaveVel)) THEN
i1_l = LBOUND(SrcInitInputData%WaveVel,1)
i1_u = UBOUND(SrcInitInputData%WaveVel,1)
@@ -901,6 +914,7 @@ SUBROUTINE MD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg
Int_BufSz = Int_BufSz + SIZE(InData%OutList)*LEN(InData%OutList) ! OutList
END IF
Int_BufSz = Int_BufSz + 1 ! Linearize
+ Int_BufSz = Int_BufSz + 1 ! VisMeshes
Int_BufSz = Int_BufSz + 1 ! WaveVel allocated yes/no
IF ( ALLOCATED(InData%WaveVel) ) THEN
Int_BufSz = Int_BufSz + 2*3 ! WaveVel upper/lower bounds for each dimension
@@ -1062,6 +1076,8 @@ SUBROUTINE MD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg
END IF
IntKiBuf(Int_Xferred) = TRANSFER(InData%Linearize, IntKiBuf(1))
Int_Xferred = Int_Xferred + 1
+ IntKiBuf(Int_Xferred) = TRANSFER(InData%VisMeshes, IntKiBuf(1))
+ Int_Xferred = Int_Xferred + 1
IF ( .NOT. ALLOCATED(InData%WaveVel) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
@@ -1328,6 +1344,8 @@ SUBROUTINE MD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err
END IF
OutData%Linearize = TRANSFER(IntKiBuf(Int_Xferred), OutData%Linearize)
Int_Xferred = Int_Xferred + 1
+ OutData%VisMeshes = TRANSFER(IntKiBuf(Int_Xferred), OutData%VisMeshes)
+ Int_Xferred = Int_Xferred + 1
IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! WaveVel not allocated
Int_Xferred = Int_Xferred + 1
ELSE
@@ -6876,6 +6894,192 @@ SUBROUTINE MD_UnPackOutParmType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E
Int_Xferred = Int_Xferred + 1
END SUBROUTINE MD_UnPackOutParmType
+ SUBROUTINE MD_CopyVisDiam( SrcVisDiamData, DstVisDiamData, CtrlCode, ErrStat, ErrMsg )
+ TYPE(VisDiam), INTENT(IN) :: SrcVisDiamData
+ TYPE(VisDiam), INTENT(INOUT) :: DstVisDiamData
+ INTEGER(IntKi), INTENT(IN ) :: CtrlCode
+ INTEGER(IntKi), INTENT( OUT) :: ErrStat
+ CHARACTER(*), INTENT( OUT) :: ErrMsg
+! Local
+ INTEGER(IntKi) :: i,j,k
+ INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1
+ INTEGER(IntKi) :: ErrStat2
+ CHARACTER(ErrMsgLen) :: ErrMsg2
+ CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyVisDiam'
+!
+ ErrStat = ErrID_None
+ ErrMsg = ""
+IF (ALLOCATED(SrcVisDiamData%Diam)) THEN
+ i1_l = LBOUND(SrcVisDiamData%Diam,1)
+ i1_u = UBOUND(SrcVisDiamData%Diam,1)
+ IF (.NOT. ALLOCATED(DstVisDiamData%Diam)) THEN
+ ALLOCATE(DstVisDiamData%Diam(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVisDiamData%Diam.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DstVisDiamData%Diam = SrcVisDiamData%Diam
+ENDIF
+ END SUBROUTINE MD_CopyVisDiam
+
+ SUBROUTINE MD_DestroyVisDiam( VisDiamData, ErrStat, ErrMsg, DEALLOCATEpointers )
+ TYPE(VisDiam), INTENT(INOUT) :: VisDiamData
+ INTEGER(IntKi), INTENT( OUT) :: ErrStat
+ CHARACTER(*), INTENT( OUT) :: ErrMsg
+ LOGICAL,OPTIONAL,INTENT(IN ) :: DEALLOCATEpointers
+
+ INTEGER(IntKi) :: i, i1, i2, i3, i4, i5
+ LOGICAL :: DEALLOCATEpointers_local
+ INTEGER(IntKi) :: ErrStat2
+ CHARACTER(ErrMsgLen) :: ErrMsg2
+ CHARACTER(*), PARAMETER :: RoutineName = 'MD_DestroyVisDiam'
+
+ ErrStat = ErrID_None
+ ErrMsg = ""
+
+ IF (PRESENT(DEALLOCATEpointers)) THEN
+ DEALLOCATEpointers_local = DEALLOCATEpointers
+ ELSE
+ DEALLOCATEpointers_local = .true.
+ END IF
+
+IF (ALLOCATED(VisDiamData%Diam)) THEN
+ DEALLOCATE(VisDiamData%Diam)
+ENDIF
+ END SUBROUTINE MD_DestroyVisDiam
+
+ SUBROUTINE MD_PackVisDiam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly )
+ REAL(ReKi), ALLOCATABLE, INTENT( OUT) :: ReKiBuf(:)
+ REAL(DbKi), ALLOCATABLE, INTENT( OUT) :: DbKiBuf(:)
+ INTEGER(IntKi), ALLOCATABLE, INTENT( OUT) :: IntKiBuf(:)
+ TYPE(VisDiam), INTENT(IN) :: InData
+ INTEGER(IntKi), INTENT( OUT) :: ErrStat
+ CHARACTER(*), INTENT( OUT) :: ErrMsg
+ LOGICAL,OPTIONAL, INTENT(IN ) :: SizeOnly
+ ! Local variables
+ INTEGER(IntKi) :: Re_BufSz
+ INTEGER(IntKi) :: Re_Xferred
+ INTEGER(IntKi) :: Db_BufSz
+ INTEGER(IntKi) :: Db_Xferred
+ INTEGER(IntKi) :: Int_BufSz
+ INTEGER(IntKi) :: Int_Xferred
+ INTEGER(IntKi) :: i,i1,i2,i3,i4,i5
+ LOGICAL :: OnlySize ! if present and true, do not pack, just allocate buffers
+ INTEGER(IntKi) :: ErrStat2
+ CHARACTER(ErrMsgLen) :: ErrMsg2
+ CHARACTER(*), PARAMETER :: RoutineName = 'MD_PackVisDiam'
+ ! buffers to store subtypes, if any
+ REAL(ReKi), ALLOCATABLE :: Re_Buf(:)
+ REAL(DbKi), ALLOCATABLE :: Db_Buf(:)
+ INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:)
+
+ OnlySize = .FALSE.
+ IF ( PRESENT(SizeOnly) ) THEN
+ OnlySize = SizeOnly
+ ENDIF
+ !
+ ErrStat = ErrID_None
+ ErrMsg = ""
+ Re_BufSz = 0
+ Db_BufSz = 0
+ Int_BufSz = 0
+ Int_BufSz = Int_BufSz + 1 ! Diam allocated yes/no
+ IF ( ALLOCATED(InData%Diam) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! Diam upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%Diam) ! Diam
+ END IF
+ IF ( Re_BufSz .GT. 0 ) THEN
+ ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating ReKiBuf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ IF ( Db_BufSz .GT. 0 ) THEN
+ ALLOCATE( DbKiBuf( Db_BufSz ), STAT=ErrStat2 )
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DbKiBuf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ IF ( Int_BufSz .GT. 0 ) THEN
+ ALLOCATE( IntKiBuf( Int_BufSz ), STAT=ErrStat2 )
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating IntKiBuf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ IF(OnlySize) RETURN ! return early if only trying to allocate buffers (not pack them)
+
+ Re_Xferred = 1
+ Db_Xferred = 1
+ Int_Xferred = 1
+
+ IF ( .NOT. ALLOCATED(InData%Diam) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%Diam,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%Diam,1)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i1 = LBOUND(InData%Diam,1), UBOUND(InData%Diam,1)
+ ReKiBuf(Re_Xferred) = InData%Diam(i1)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END IF
+ END SUBROUTINE MD_PackVisDiam
+
+ SUBROUTINE MD_UnPackVisDiam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
+ REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:)
+ REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:)
+ INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:)
+ TYPE(VisDiam), INTENT(INOUT) :: OutData
+ INTEGER(IntKi), INTENT( OUT) :: ErrStat
+ CHARACTER(*), INTENT( OUT) :: ErrMsg
+ ! Local variables
+ INTEGER(IntKi) :: Buf_size
+ INTEGER(IntKi) :: Re_Xferred
+ INTEGER(IntKi) :: Db_Xferred
+ INTEGER(IntKi) :: Int_Xferred
+ INTEGER(IntKi) :: i
+ INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1
+ INTEGER(IntKi) :: ErrStat2
+ CHARACTER(ErrMsgLen) :: ErrMsg2
+ CHARACTER(*), PARAMETER :: RoutineName = 'MD_UnPackVisDiam'
+ ! buffers to store meshes, if any
+ REAL(ReKi), ALLOCATABLE :: Re_Buf(:)
+ REAL(DbKi), ALLOCATABLE :: Db_Buf(:)
+ INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:)
+ !
+ ErrStat = ErrID_None
+ ErrMsg = ""
+ Re_Xferred = 1
+ Db_Xferred = 1
+ Int_Xferred = 1
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! Diam not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%Diam)) DEALLOCATE(OutData%Diam)
+ ALLOCATE(OutData%Diam(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%Diam.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i1 = LBOUND(OutData%Diam,1), UBOUND(OutData%Diam,1)
+ OutData%Diam(i1) = REAL(ReKiBuf(Re_Xferred), SiKi)
+ Re_Xferred = Re_Xferred + 1
+ END DO
+ END IF
+ END SUBROUTINE MD_UnPackVisDiam
+
SUBROUTINE MD_CopyInitOutput( SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg )
TYPE(MD_InitOutputType), INTENT(IN) :: SrcInitOutputData
TYPE(MD_InitOutputType), INTENT(INOUT) :: DstInitOutputData
@@ -11197,6 +11401,23 @@ SUBROUTINE MD_CopyParam( SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg )
END IF
END IF
DstParamData%dxIdx_map2_xStateIdx = SrcParamData%dxIdx_map2_xStateIdx
+ENDIF
+ DstParamData%VisMeshes = SrcParamData%VisMeshes
+IF (ALLOCATED(SrcParamData%VisRodsDiam)) THEN
+ i1_l = LBOUND(SrcParamData%VisRodsDiam,1)
+ i1_u = UBOUND(SrcParamData%VisRodsDiam,1)
+ IF (.NOT. ALLOCATED(DstParamData%VisRodsDiam)) THEN
+ ALLOCATE(DstParamData%VisRodsDiam(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%VisRodsDiam.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DO i1 = LBOUND(SrcParamData%VisRodsDiam,1), UBOUND(SrcParamData%VisRodsDiam,1)
+ CALL MD_Copyvisdiam( SrcParamData%VisRodsDiam(i1), DstParamData%VisRodsDiam(i1), CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
+ ENDDO
ENDIF
END SUBROUTINE MD_CopyParam
@@ -11293,6 +11514,13 @@ SUBROUTINE MD_DestroyParam( ParamData, ErrStat, ErrMsg, DEALLOCATEpointers )
ENDIF
IF (ALLOCATED(ParamData%dxIdx_map2_xStateIdx)) THEN
DEALLOCATE(ParamData%dxIdx_map2_xStateIdx)
+ENDIF
+IF (ALLOCATED(ParamData%VisRodsDiam)) THEN
+DO i1 = LBOUND(ParamData%VisRodsDiam,1), UBOUND(ParamData%VisRodsDiam,1)
+ CALL MD_Destroyvisdiam( ParamData%VisRodsDiam(i1), ErrStat2, ErrMsg2, DEALLOCATEpointers_local )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ENDDO
+ DEALLOCATE(ParamData%VisRodsDiam)
ENDIF
END SUBROUTINE MD_DestroyParam
@@ -11510,6 +11738,30 @@ SUBROUTINE MD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si
IF ( ALLOCATED(InData%dxIdx_map2_xStateIdx) ) THEN
Int_BufSz = Int_BufSz + 2*1 ! dxIdx_map2_xStateIdx upper/lower bounds for each dimension
Int_BufSz = Int_BufSz + SIZE(InData%dxIdx_map2_xStateIdx) ! dxIdx_map2_xStateIdx
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! VisMeshes
+ Int_BufSz = Int_BufSz + 1 ! VisRodsDiam allocated yes/no
+ IF ( ALLOCATED(InData%VisRodsDiam) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! VisRodsDiam upper/lower bounds for each dimension
+ DO i1 = LBOUND(InData%VisRodsDiam,1), UBOUND(InData%VisRodsDiam,1)
+ Int_BufSz = Int_BufSz + 3 ! VisRodsDiam: size of buffers for each call to pack subtype
+ CALL MD_Packvisdiam( Re_Buf, Db_Buf, Int_Buf, InData%VisRodsDiam(i1), ErrStat2, ErrMsg2, .TRUE. ) ! VisRodsDiam
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN ! VisRodsDiam
+ Re_BufSz = Re_BufSz + SIZE( Re_Buf )
+ DEALLOCATE(Re_Buf)
+ END IF
+ IF(ALLOCATED(Db_Buf)) THEN ! VisRodsDiam
+ Db_BufSz = Db_BufSz + SIZE( Db_Buf )
+ DEALLOCATE(Db_Buf)
+ END IF
+ IF(ALLOCATED(Int_Buf)) THEN ! VisRodsDiam
+ Int_BufSz = Int_BufSz + SIZE( Int_Buf )
+ DEALLOCATE(Int_Buf)
+ END IF
+ END DO
END IF
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
@@ -12131,6 +12383,49 @@ SUBROUTINE MD_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, Si
IntKiBuf(Int_Xferred) = InData%dxIdx_map2_xStateIdx(i1)
Int_Xferred = Int_Xferred + 1
END DO
+ END IF
+ IntKiBuf(Int_Xferred) = TRANSFER(InData%VisMeshes, IntKiBuf(1))
+ Int_Xferred = Int_Xferred + 1
+ IF ( .NOT. ALLOCATED(InData%VisRodsDiam) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%VisRodsDiam,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VisRodsDiam,1)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i1 = LBOUND(InData%VisRodsDiam,1), UBOUND(InData%VisRodsDiam,1)
+ CALL MD_Packvisdiam( Re_Buf, Db_Buf, Int_Buf, InData%VisRodsDiam(i1), ErrStat2, ErrMsg2, OnlySize ) ! VisRodsDiam
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf
+ Re_Xferred = Re_Xferred + SIZE(Re_Buf)
+ DEALLOCATE(Re_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Db_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf
+ Db_Xferred = Db_Xferred + SIZE(Db_Buf)
+ DEALLOCATE(Db_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Int_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf
+ Int_Xferred = Int_Xferred + SIZE(Int_Buf)
+ DEALLOCATE(Int_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ END DO
END IF
END SUBROUTINE MD_PackParam
@@ -12839,46 +13134,104 @@ SUBROUTINE MD_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg
Int_Xferred = Int_Xferred + 1
END DO
END IF
- END SUBROUTINE MD_UnPackParam
-
- SUBROUTINE MD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg )
- TYPE(MD_InputType), INTENT(INOUT) :: SrcInputData
- TYPE(MD_InputType), INTENT(INOUT) :: DstInputData
- INTEGER(IntKi), INTENT(IN ) :: CtrlCode
- INTEGER(IntKi), INTENT( OUT) :: ErrStat
- CHARACTER(*), INTENT( OUT) :: ErrMsg
-! Local
- INTEGER(IntKi) :: i,j,k
- INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1
- INTEGER(IntKi) :: ErrStat2
- CHARACTER(ErrMsgLen) :: ErrMsg2
- CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyInput'
-!
- ErrStat = ErrID_None
- ErrMsg = ""
-IF (ALLOCATED(SrcInputData%CoupledKinematics)) THEN
- i1_l = LBOUND(SrcInputData%CoupledKinematics,1)
- i1_u = UBOUND(SrcInputData%CoupledKinematics,1)
- IF (.NOT. ALLOCATED(DstInputData%CoupledKinematics)) THEN
- ALLOCATE(DstInputData%CoupledKinematics(i1_l:i1_u),STAT=ErrStat2)
+ OutData%VisMeshes = TRANSFER(IntKiBuf(Int_Xferred), OutData%VisMeshes)
+ Int_Xferred = Int_Xferred + 1
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VisRodsDiam not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%VisRodsDiam)) DEALLOCATE(OutData%VisRodsDiam)
+ ALLOCATE(OutData%VisRodsDiam(i1_l:i1_u),STAT=ErrStat2)
IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%CoupledKinematics.', ErrStat, ErrMsg,RoutineName)
- RETURN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VisRodsDiam.', ErrStat, ErrMsg,RoutineName)
+ RETURN
END IF
- END IF
- DO i1 = LBOUND(SrcInputData%CoupledKinematics,1), UBOUND(SrcInputData%CoupledKinematics,1)
- CALL MeshCopy( SrcInputData%CoupledKinematics(i1), DstInputData%CoupledKinematics(i1), CtrlCode, ErrStat2, ErrMsg2 )
- CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
- IF (ErrStat>=AbortErrLev) RETURN
- ENDDO
-ENDIF
-IF (ALLOCATED(SrcInputData%DeltaL)) THEN
- i1_l = LBOUND(SrcInputData%DeltaL,1)
- i1_u = UBOUND(SrcInputData%DeltaL,1)
- IF (.NOT. ALLOCATED(DstInputData%DeltaL)) THEN
- ALLOCATE(DstInputData%DeltaL(i1_l:i1_u),STAT=ErrStat2)
- IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%DeltaL.', ErrStat, ErrMsg,RoutineName)
+ DO i1 = LBOUND(OutData%VisRodsDiam,1), UBOUND(OutData%VisRodsDiam,1)
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )
+ Re_Xferred = Re_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )
+ Db_Xferred = Db_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )
+ Int_Xferred = Int_Xferred + Buf_size
+ END IF
+ CALL MD_Unpackvisdiam( Re_Buf, Db_Buf, Int_Buf, OutData%VisRodsDiam(i1), ErrStat2, ErrMsg2 ) ! VisRodsDiam
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
+ IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
+ IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
+ END DO
+ END IF
+ END SUBROUTINE MD_UnPackParam
+
+ SUBROUTINE MD_CopyInput( SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg )
+ TYPE(MD_InputType), INTENT(INOUT) :: SrcInputData
+ TYPE(MD_InputType), INTENT(INOUT) :: DstInputData
+ INTEGER(IntKi), INTENT(IN ) :: CtrlCode
+ INTEGER(IntKi), INTENT( OUT) :: ErrStat
+ CHARACTER(*), INTENT( OUT) :: ErrMsg
+! Local
+ INTEGER(IntKi) :: i,j,k
+ INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1
+ INTEGER(IntKi) :: ErrStat2
+ CHARACTER(ErrMsgLen) :: ErrMsg2
+ CHARACTER(*), PARAMETER :: RoutineName = 'MD_CopyInput'
+!
+ ErrStat = ErrID_None
+ ErrMsg = ""
+IF (ALLOCATED(SrcInputData%CoupledKinematics)) THEN
+ i1_l = LBOUND(SrcInputData%CoupledKinematics,1)
+ i1_u = UBOUND(SrcInputData%CoupledKinematics,1)
+ IF (.NOT. ALLOCATED(DstInputData%CoupledKinematics)) THEN
+ ALLOCATE(DstInputData%CoupledKinematics(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%CoupledKinematics.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DO i1 = LBOUND(SrcInputData%CoupledKinematics,1), UBOUND(SrcInputData%CoupledKinematics,1)
+ CALL MeshCopy( SrcInputData%CoupledKinematics(i1), DstInputData%CoupledKinematics(i1), CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
+ ENDDO
+ENDIF
+IF (ALLOCATED(SrcInputData%DeltaL)) THEN
+ i1_l = LBOUND(SrcInputData%DeltaL,1)
+ i1_u = UBOUND(SrcInputData%DeltaL,1)
+ IF (.NOT. ALLOCATED(DstInputData%DeltaL)) THEN
+ ALLOCATE(DstInputData%DeltaL(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%DeltaL.', ErrStat, ErrMsg,RoutineName)
RETURN
END IF
END IF
@@ -13266,6 +13619,70 @@ SUBROUTINE MD_CopyOutput( SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMs
END IF
END IF
DstOutputData%WriteOutput = SrcOutputData%WriteOutput
+ENDIF
+IF (ALLOCATED(SrcOutputData%VisLinesMesh)) THEN
+ i1_l = LBOUND(SrcOutputData%VisLinesMesh,1)
+ i1_u = UBOUND(SrcOutputData%VisLinesMesh,1)
+ IF (.NOT. ALLOCATED(DstOutputData%VisLinesMesh)) THEN
+ ALLOCATE(DstOutputData%VisLinesMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%VisLinesMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DO i1 = LBOUND(SrcOutputData%VisLinesMesh,1), UBOUND(SrcOutputData%VisLinesMesh,1)
+ CALL MeshCopy( SrcOutputData%VisLinesMesh(i1), DstOutputData%VisLinesMesh(i1), CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
+ ENDDO
+ENDIF
+IF (ALLOCATED(SrcOutputData%VisRodsMesh)) THEN
+ i1_l = LBOUND(SrcOutputData%VisRodsMesh,1)
+ i1_u = UBOUND(SrcOutputData%VisRodsMesh,1)
+ IF (.NOT. ALLOCATED(DstOutputData%VisRodsMesh)) THEN
+ ALLOCATE(DstOutputData%VisRodsMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%VisRodsMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DO i1 = LBOUND(SrcOutputData%VisRodsMesh,1), UBOUND(SrcOutputData%VisRodsMesh,1)
+ CALL MeshCopy( SrcOutputData%VisRodsMesh(i1), DstOutputData%VisRodsMesh(i1), CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
+ ENDDO
+ENDIF
+IF (ALLOCATED(SrcOutputData%VisBodiesMesh)) THEN
+ i1_l = LBOUND(SrcOutputData%VisBodiesMesh,1)
+ i1_u = UBOUND(SrcOutputData%VisBodiesMesh,1)
+ IF (.NOT. ALLOCATED(DstOutputData%VisBodiesMesh)) THEN
+ ALLOCATE(DstOutputData%VisBodiesMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%VisBodiesMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DO i1 = LBOUND(SrcOutputData%VisBodiesMesh,1), UBOUND(SrcOutputData%VisBodiesMesh,1)
+ CALL MeshCopy( SrcOutputData%VisBodiesMesh(i1), DstOutputData%VisBodiesMesh(i1), CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
+ ENDDO
+ENDIF
+IF (ALLOCATED(SrcOutputData%VisAnchsMesh)) THEN
+ i1_l = LBOUND(SrcOutputData%VisAnchsMesh,1)
+ i1_u = UBOUND(SrcOutputData%VisAnchsMesh,1)
+ IF (.NOT. ALLOCATED(DstOutputData%VisAnchsMesh)) THEN
+ ALLOCATE(DstOutputData%VisAnchsMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%VisAnchsMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ END IF
+ DO i1 = LBOUND(SrcOutputData%VisAnchsMesh,1), UBOUND(SrcOutputData%VisAnchsMesh,1)
+ CALL MeshCopy( SrcOutputData%VisAnchsMesh(i1), DstOutputData%VisAnchsMesh(i1), CtrlCode, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat>=AbortErrLev) RETURN
+ ENDDO
ENDIF
END SUBROUTINE MD_CopyOutput
@@ -13299,6 +13716,34 @@ SUBROUTINE MD_DestroyOutput( OutputData, ErrStat, ErrMsg, DEALLOCATEpointers )
ENDIF
IF (ALLOCATED(OutputData%WriteOutput)) THEN
DEALLOCATE(OutputData%WriteOutput)
+ENDIF
+IF (ALLOCATED(OutputData%VisLinesMesh)) THEN
+DO i1 = LBOUND(OutputData%VisLinesMesh,1), UBOUND(OutputData%VisLinesMesh,1)
+ CALL MeshDestroy( OutputData%VisLinesMesh(i1), ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ENDDO
+ DEALLOCATE(OutputData%VisLinesMesh)
+ENDIF
+IF (ALLOCATED(OutputData%VisRodsMesh)) THEN
+DO i1 = LBOUND(OutputData%VisRodsMesh,1), UBOUND(OutputData%VisRodsMesh,1)
+ CALL MeshDestroy( OutputData%VisRodsMesh(i1), ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ENDDO
+ DEALLOCATE(OutputData%VisRodsMesh)
+ENDIF
+IF (ALLOCATED(OutputData%VisBodiesMesh)) THEN
+DO i1 = LBOUND(OutputData%VisBodiesMesh,1), UBOUND(OutputData%VisBodiesMesh,1)
+ CALL MeshDestroy( OutputData%VisBodiesMesh(i1), ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ENDDO
+ DEALLOCATE(OutputData%VisBodiesMesh)
+ENDIF
+IF (ALLOCATED(OutputData%VisAnchsMesh)) THEN
+DO i1 = LBOUND(OutputData%VisAnchsMesh,1), UBOUND(OutputData%VisAnchsMesh,1)
+ CALL MeshDestroy( OutputData%VisAnchsMesh(i1), ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ENDDO
+ DEALLOCATE(OutputData%VisAnchsMesh)
ENDIF
END SUBROUTINE MD_DestroyOutput
@@ -13366,6 +13811,98 @@ SUBROUTINE MD_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, S
Int_BufSz = Int_BufSz + 2*1 ! WriteOutput upper/lower bounds for each dimension
Re_BufSz = Re_BufSz + SIZE(InData%WriteOutput) ! WriteOutput
END IF
+ Int_BufSz = Int_BufSz + 1 ! VisLinesMesh allocated yes/no
+ IF ( ALLOCATED(InData%VisLinesMesh) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! VisLinesMesh upper/lower bounds for each dimension
+ DO i1 = LBOUND(InData%VisLinesMesh,1), UBOUND(InData%VisLinesMesh,1)
+ Int_BufSz = Int_BufSz + 3 ! VisLinesMesh: size of buffers for each call to pack subtype
+ CALL MeshPack( InData%VisLinesMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! VisLinesMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN ! VisLinesMesh
+ Re_BufSz = Re_BufSz + SIZE( Re_Buf )
+ DEALLOCATE(Re_Buf)
+ END IF
+ IF(ALLOCATED(Db_Buf)) THEN ! VisLinesMesh
+ Db_BufSz = Db_BufSz + SIZE( Db_Buf )
+ DEALLOCATE(Db_Buf)
+ END IF
+ IF(ALLOCATED(Int_Buf)) THEN ! VisLinesMesh
+ Int_BufSz = Int_BufSz + SIZE( Int_Buf )
+ DEALLOCATE(Int_Buf)
+ END IF
+ END DO
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! VisRodsMesh allocated yes/no
+ IF ( ALLOCATED(InData%VisRodsMesh) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! VisRodsMesh upper/lower bounds for each dimension
+ DO i1 = LBOUND(InData%VisRodsMesh,1), UBOUND(InData%VisRodsMesh,1)
+ Int_BufSz = Int_BufSz + 3 ! VisRodsMesh: size of buffers for each call to pack subtype
+ CALL MeshPack( InData%VisRodsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! VisRodsMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN ! VisRodsMesh
+ Re_BufSz = Re_BufSz + SIZE( Re_Buf )
+ DEALLOCATE(Re_Buf)
+ END IF
+ IF(ALLOCATED(Db_Buf)) THEN ! VisRodsMesh
+ Db_BufSz = Db_BufSz + SIZE( Db_Buf )
+ DEALLOCATE(Db_Buf)
+ END IF
+ IF(ALLOCATED(Int_Buf)) THEN ! VisRodsMesh
+ Int_BufSz = Int_BufSz + SIZE( Int_Buf )
+ DEALLOCATE(Int_Buf)
+ END IF
+ END DO
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! VisBodiesMesh allocated yes/no
+ IF ( ALLOCATED(InData%VisBodiesMesh) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! VisBodiesMesh upper/lower bounds for each dimension
+ DO i1 = LBOUND(InData%VisBodiesMesh,1), UBOUND(InData%VisBodiesMesh,1)
+ Int_BufSz = Int_BufSz + 3 ! VisBodiesMesh: size of buffers for each call to pack subtype
+ CALL MeshPack( InData%VisBodiesMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! VisBodiesMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN ! VisBodiesMesh
+ Re_BufSz = Re_BufSz + SIZE( Re_Buf )
+ DEALLOCATE(Re_Buf)
+ END IF
+ IF(ALLOCATED(Db_Buf)) THEN ! VisBodiesMesh
+ Db_BufSz = Db_BufSz + SIZE( Db_Buf )
+ DEALLOCATE(Db_Buf)
+ END IF
+ IF(ALLOCATED(Int_Buf)) THEN ! VisBodiesMesh
+ Int_BufSz = Int_BufSz + SIZE( Int_Buf )
+ DEALLOCATE(Int_Buf)
+ END IF
+ END DO
+ END IF
+ Int_BufSz = Int_BufSz + 1 ! VisAnchsMesh allocated yes/no
+ IF ( ALLOCATED(InData%VisAnchsMesh) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! VisAnchsMesh upper/lower bounds for each dimension
+ DO i1 = LBOUND(InData%VisAnchsMesh,1), UBOUND(InData%VisAnchsMesh,1)
+ Int_BufSz = Int_BufSz + 3 ! VisAnchsMesh: size of buffers for each call to pack subtype
+ CALL MeshPack( InData%VisAnchsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, .TRUE. ) ! VisAnchsMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN ! VisAnchsMesh
+ Re_BufSz = Re_BufSz + SIZE( Re_Buf )
+ DEALLOCATE(Re_Buf)
+ END IF
+ IF(ALLOCATED(Db_Buf)) THEN ! VisAnchsMesh
+ Db_BufSz = Db_BufSz + SIZE( Db_Buf )
+ DEALLOCATE(Db_Buf)
+ END IF
+ IF(ALLOCATED(Int_Buf)) THEN ! VisAnchsMesh
+ Int_BufSz = Int_BufSz + SIZE( Int_Buf )
+ DEALLOCATE(Int_Buf)
+ END IF
+ END DO
+ END IF
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
IF (ErrStat2 /= 0) THEN
@@ -13449,49 +13986,213 @@ SUBROUTINE MD_PackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, S
Re_Xferred = Re_Xferred + 1
END DO
END IF
- END SUBROUTINE MD_PackOutput
+ IF ( .NOT. ALLOCATED(InData%VisLinesMesh) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%VisLinesMesh,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VisLinesMesh,1)
+ Int_Xferred = Int_Xferred + 2
- SUBROUTINE MD_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
- REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:)
- REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:)
- INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:)
- TYPE(MD_OutputType), INTENT(INOUT) :: OutData
- INTEGER(IntKi), INTENT( OUT) :: ErrStat
- CHARACTER(*), INTENT( OUT) :: ErrMsg
- ! Local variables
- INTEGER(IntKi) :: Buf_size
- INTEGER(IntKi) :: Re_Xferred
- INTEGER(IntKi) :: Db_Xferred
- INTEGER(IntKi) :: Int_Xferred
- INTEGER(IntKi) :: i
- INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1
- INTEGER(IntKi) :: ErrStat2
- CHARACTER(ErrMsgLen) :: ErrMsg2
- CHARACTER(*), PARAMETER :: RoutineName = 'MD_UnPackOutput'
- ! buffers to store meshes, if any
- REAL(ReKi), ALLOCATABLE :: Re_Buf(:)
- REAL(DbKi), ALLOCATABLE :: Db_Buf(:)
- INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:)
- !
- ErrStat = ErrID_None
- ErrMsg = ""
- Re_Xferred = 1
- Db_Xferred = 1
- Int_Xferred = 1
- IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CoupledLoads not allocated
+ DO i1 = LBOUND(InData%VisLinesMesh,1), UBOUND(InData%VisLinesMesh,1)
+ CALL MeshPack( InData%VisLinesMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! VisLinesMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf
+ Re_Xferred = Re_Xferred + SIZE(Re_Buf)
+ DEALLOCATE(Re_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Db_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf
+ Db_Xferred = Db_Xferred + SIZE(Db_Buf)
+ DEALLOCATE(Db_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Int_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf
+ Int_Xferred = Int_Xferred + SIZE(Int_Buf)
+ DEALLOCATE(Int_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%VisRodsMesh) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
ELSE
+ IntKiBuf( Int_Xferred ) = 1
Int_Xferred = Int_Xferred + 1
- i1_l = IntKiBuf( Int_Xferred )
- i1_u = IntKiBuf( Int_Xferred + 1)
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%VisRodsMesh,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VisRodsMesh,1)
Int_Xferred = Int_Xferred + 2
- IF (ALLOCATED(OutData%CoupledLoads)) DEALLOCATE(OutData%CoupledLoads)
- ALLOCATE(OutData%CoupledLoads(i1_l:i1_u),STAT=ErrStat2)
- IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoupledLoads.', ErrStat, ErrMsg,RoutineName)
- RETURN
- END IF
- DO i1 = LBOUND(OutData%CoupledLoads,1), UBOUND(OutData%CoupledLoads,1)
+
+ DO i1 = LBOUND(InData%VisRodsMesh,1), UBOUND(InData%VisRodsMesh,1)
+ CALL MeshPack( InData%VisRodsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! VisRodsMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf
+ Re_Xferred = Re_Xferred + SIZE(Re_Buf)
+ DEALLOCATE(Re_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Db_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf
+ Db_Xferred = Db_Xferred + SIZE(Db_Buf)
+ DEALLOCATE(Db_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Int_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf
+ Int_Xferred = Int_Xferred + SIZE(Int_Buf)
+ DEALLOCATE(Int_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%VisBodiesMesh) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%VisBodiesMesh,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VisBodiesMesh,1)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i1 = LBOUND(InData%VisBodiesMesh,1), UBOUND(InData%VisBodiesMesh,1)
+ CALL MeshPack( InData%VisBodiesMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! VisBodiesMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf
+ Re_Xferred = Re_Xferred + SIZE(Re_Buf)
+ DEALLOCATE(Re_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Db_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf
+ Db_Xferred = Db_Xferred + SIZE(Db_Buf)
+ DEALLOCATE(Db_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Int_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf
+ Int_Xferred = Int_Xferred + SIZE(Int_Buf)
+ DEALLOCATE(Int_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ END DO
+ END IF
+ IF ( .NOT. ALLOCATED(InData%VisAnchsMesh) ) THEN
+ IntKiBuf( Int_Xferred ) = 0
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ IntKiBuf( Int_Xferred ) = 1
+ Int_Xferred = Int_Xferred + 1
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%VisAnchsMesh,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%VisAnchsMesh,1)
+ Int_Xferred = Int_Xferred + 2
+
+ DO i1 = LBOUND(InData%VisAnchsMesh,1), UBOUND(InData%VisAnchsMesh,1)
+ CALL MeshPack( InData%VisAnchsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2, OnlySize ) ! VisAnchsMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf
+ Re_Xferred = Re_Xferred + SIZE(Re_Buf)
+ DEALLOCATE(Re_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Db_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf
+ Db_Xferred = Db_Xferred + SIZE(Db_Buf)
+ DEALLOCATE(Db_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ IF(ALLOCATED(Int_Buf)) THEN
+ IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1
+ IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf
+ Int_Xferred = Int_Xferred + SIZE(Int_Buf)
+ DEALLOCATE(Int_Buf)
+ ELSE
+ IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1
+ ENDIF
+ END DO
+ END IF
+ END SUBROUTINE MD_PackOutput
+
+ SUBROUTINE MD_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg )
+ REAL(ReKi), ALLOCATABLE, INTENT(IN ) :: ReKiBuf(:)
+ REAL(DbKi), ALLOCATABLE, INTENT(IN ) :: DbKiBuf(:)
+ INTEGER(IntKi), ALLOCATABLE, INTENT(IN ) :: IntKiBuf(:)
+ TYPE(MD_OutputType), INTENT(INOUT) :: OutData
+ INTEGER(IntKi), INTENT( OUT) :: ErrStat
+ CHARACTER(*), INTENT( OUT) :: ErrMsg
+ ! Local variables
+ INTEGER(IntKi) :: Buf_size
+ INTEGER(IntKi) :: Re_Xferred
+ INTEGER(IntKi) :: Db_Xferred
+ INTEGER(IntKi) :: Int_Xferred
+ INTEGER(IntKi) :: i
+ INTEGER(IntKi) :: i1, i1_l, i1_u ! bounds (upper/lower) for an array dimension 1
+ INTEGER(IntKi) :: ErrStat2
+ CHARACTER(ErrMsgLen) :: ErrMsg2
+ CHARACTER(*), PARAMETER :: RoutineName = 'MD_UnPackOutput'
+ ! buffers to store meshes, if any
+ REAL(ReKi), ALLOCATABLE :: Re_Buf(:)
+ REAL(DbKi), ALLOCATABLE :: Db_Buf(:)
+ INTEGER(IntKi), ALLOCATABLE :: Int_Buf(:)
+ !
+ ErrStat = ErrID_None
+ ErrMsg = ""
+ Re_Xferred = 1
+ Db_Xferred = 1
+ Int_Xferred = 1
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! CoupledLoads not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%CoupledLoads)) DEALLOCATE(OutData%CoupledLoads)
+ ALLOCATE(OutData%CoupledLoads(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%CoupledLoads.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i1 = LBOUND(OutData%CoupledLoads,1), UBOUND(OutData%CoupledLoads,1)
Buf_size=IntKiBuf( Int_Xferred )
Int_Xferred = Int_Xferred + 1
IF(Buf_size > 0) THEN
@@ -13552,6 +14253,230 @@ SUBROUTINE MD_UnPackOutput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg
Re_Xferred = Re_Xferred + 1
END DO
END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VisLinesMesh not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%VisLinesMesh)) DEALLOCATE(OutData%VisLinesMesh)
+ ALLOCATE(OutData%VisLinesMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VisLinesMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i1 = LBOUND(OutData%VisLinesMesh,1), UBOUND(OutData%VisLinesMesh,1)
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )
+ Re_Xferred = Re_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )
+ Db_Xferred = Db_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )
+ Int_Xferred = Int_Xferred + Buf_size
+ END IF
+ CALL MeshUnpack( OutData%VisLinesMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! VisLinesMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
+ IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
+ IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
+ END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VisRodsMesh not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%VisRodsMesh)) DEALLOCATE(OutData%VisRodsMesh)
+ ALLOCATE(OutData%VisRodsMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VisRodsMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i1 = LBOUND(OutData%VisRodsMesh,1), UBOUND(OutData%VisRodsMesh,1)
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )
+ Re_Xferred = Re_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )
+ Db_Xferred = Db_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )
+ Int_Xferred = Int_Xferred + Buf_size
+ END IF
+ CALL MeshUnpack( OutData%VisRodsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! VisRodsMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
+ IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
+ IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
+ END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VisBodiesMesh not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%VisBodiesMesh)) DEALLOCATE(OutData%VisBodiesMesh)
+ ALLOCATE(OutData%VisBodiesMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VisBodiesMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i1 = LBOUND(OutData%VisBodiesMesh,1), UBOUND(OutData%VisBodiesMesh,1)
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )
+ Re_Xferred = Re_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )
+ Db_Xferred = Db_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )
+ Int_Xferred = Int_Xferred + Buf_size
+ END IF
+ CALL MeshUnpack( OutData%VisBodiesMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! VisBodiesMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
+ IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
+ IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
+ END DO
+ END IF
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! VisAnchsMesh not allocated
+ Int_Xferred = Int_Xferred + 1
+ ELSE
+ Int_Xferred = Int_Xferred + 1
+ i1_l = IntKiBuf( Int_Xferred )
+ i1_u = IntKiBuf( Int_Xferred + 1)
+ Int_Xferred = Int_Xferred + 2
+ IF (ALLOCATED(OutData%VisAnchsMesh)) DEALLOCATE(OutData%VisAnchsMesh)
+ ALLOCATE(OutData%VisAnchsMesh(i1_l:i1_u),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%VisAnchsMesh.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ DO i1 = LBOUND(OutData%VisAnchsMesh,1), UBOUND(OutData%VisAnchsMesh,1)
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 )
+ Re_Xferred = Re_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 )
+ Db_Xferred = Db_Xferred + Buf_size
+ END IF
+ Buf_size=IntKiBuf( Int_Xferred )
+ Int_Xferred = Int_Xferred + 1
+ IF(Buf_size > 0) THEN
+ ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2)
+ IF (ErrStat2 /= 0) THEN
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName)
+ RETURN
+ END IF
+ Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 )
+ Int_Xferred = Int_Xferred + Buf_size
+ END IF
+ CALL MeshUnpack( OutData%VisAnchsMesh(i1), Re_Buf, Db_Buf, Int_Buf, ErrStat2, ErrMsg2 ) ! VisAnchsMesh
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
+ IF (ErrStat >= AbortErrLev) RETURN
+
+ IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf )
+ IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf )
+ IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
+ END DO
+ END IF
END SUBROUTINE MD_UnPackOutput
@@ -13852,6 +14777,30 @@ SUBROUTINE MD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg
b = -(y1%WriteOutput(i1) - y2%WriteOutput(i1))
y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b * ScaleFactor
END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisLinesMesh) .AND. ALLOCATED(y1%VisLinesMesh)) THEN
+ DO i1 = LBOUND(y_out%VisLinesMesh,1),UBOUND(y_out%VisLinesMesh,1)
+ CALL MeshExtrapInterp1(y1%VisLinesMesh(i1), y2%VisLinesMesh(i1), tin, y_out%VisLinesMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisRodsMesh) .AND. ALLOCATED(y1%VisRodsMesh)) THEN
+ DO i1 = LBOUND(y_out%VisRodsMesh,1),UBOUND(y_out%VisRodsMesh,1)
+ CALL MeshExtrapInterp1(y1%VisRodsMesh(i1), y2%VisRodsMesh(i1), tin, y_out%VisRodsMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisBodiesMesh) .AND. ALLOCATED(y1%VisBodiesMesh)) THEN
+ DO i1 = LBOUND(y_out%VisBodiesMesh,1),UBOUND(y_out%VisBodiesMesh,1)
+ CALL MeshExtrapInterp1(y1%VisBodiesMesh(i1), y2%VisBodiesMesh(i1), tin, y_out%VisBodiesMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisAnchsMesh) .AND. ALLOCATED(y1%VisAnchsMesh)) THEN
+ DO i1 = LBOUND(y_out%VisAnchsMesh,1),UBOUND(y_out%VisAnchsMesh,1)
+ CALL MeshExtrapInterp1(y1%VisAnchsMesh(i1), y2%VisAnchsMesh(i1), tin, y_out%VisAnchsMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
END IF ! check if allocated
END SUBROUTINE MD_Output_ExtrapInterp1
@@ -13922,6 +14871,30 @@ SUBROUTINE MD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, Err
c = ( (t(2)-t(3))*y1%WriteOutput(i1) + t(3)*y2%WriteOutput(i1) - t(2)*y3%WriteOutput(i1) ) * scaleFactor
y_out%WriteOutput(i1) = y1%WriteOutput(i1) + b + c * t_out
END DO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisLinesMesh) .AND. ALLOCATED(y1%VisLinesMesh)) THEN
+ DO i1 = LBOUND(y_out%VisLinesMesh,1),UBOUND(y_out%VisLinesMesh,1)
+ CALL MeshExtrapInterp2(y1%VisLinesMesh(i1), y2%VisLinesMesh(i1), y3%VisLinesMesh(i1), tin, y_out%VisLinesMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisRodsMesh) .AND. ALLOCATED(y1%VisRodsMesh)) THEN
+ DO i1 = LBOUND(y_out%VisRodsMesh,1),UBOUND(y_out%VisRodsMesh,1)
+ CALL MeshExtrapInterp2(y1%VisRodsMesh(i1), y2%VisRodsMesh(i1), y3%VisRodsMesh(i1), tin, y_out%VisRodsMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisBodiesMesh) .AND. ALLOCATED(y1%VisBodiesMesh)) THEN
+ DO i1 = LBOUND(y_out%VisBodiesMesh,1),UBOUND(y_out%VisBodiesMesh,1)
+ CALL MeshExtrapInterp2(y1%VisBodiesMesh(i1), y2%VisBodiesMesh(i1), y3%VisBodiesMesh(i1), tin, y_out%VisBodiesMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
+END IF ! check if allocated
+IF (ALLOCATED(y_out%VisAnchsMesh) .AND. ALLOCATED(y1%VisAnchsMesh)) THEN
+ DO i1 = LBOUND(y_out%VisAnchsMesh,1),UBOUND(y_out%VisAnchsMesh,1)
+ CALL MeshExtrapInterp2(y1%VisAnchsMesh(i1), y2%VisAnchsMesh(i1), y3%VisAnchsMesh(i1), tin, y_out%VisAnchsMesh(i1), tin_out, ErrStat2, ErrMsg2 )
+ CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName)
+ ENDDO
END IF ! check if allocated
END SUBROUTINE MD_Output_ExtrapInterp2
diff --git a/modules/nwtc-library/src/NWTC_Num.f90 b/modules/nwtc-library/src/NWTC_Num.f90
index de4fcd8def..2daf088cca 100644
--- a/modules/nwtc-library/src/NWTC_Num.f90
+++ b/modules/nwtc-library/src/NWTC_Num.f90
@@ -6313,7 +6313,13 @@ SUBROUTINE Angles_ExtrapInterp1_R4(Angle1, Angle2, tin, Angle_out, tin_out )
REAL(R8Ki) :: t_out ! Time to which to be extrap/interpd
REAL(SiKi) :: Angle2_mod
-
+
+ ! If both inputs are the same, then the output must equal the input
+ if (Angle1 == Angle2) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
@@ -6357,7 +6363,13 @@ SUBROUTINE Angles_ExtrapInterp1_R8(Angle1, Angle2, tin, Angle_out, tin_out)
REAL(R8Ki) :: t_out ! Time to which to be extrap/interpd
REAL(R8Ki) :: Angle2_mod
-
+
+ ! If both inputs are the same, then the output must equal the input
+ if (Angle1 == Angle2) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
@@ -6400,7 +6412,13 @@ SUBROUTINE Angles_ExtrapInterp1_R4R(Angle1, Angle2, tin, Angle_out, tin_out )
REAL(SiKi) :: t_out ! Time to which to be extrap/interpd
REAL(SiKi) :: Angle2_mod
-
+
+ ! If both inputs are the same, then the output must equal the input
+ if (Angle1 == Angle2) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
@@ -6444,7 +6462,13 @@ SUBROUTINE Angles_ExtrapInterp1_R8R(Angle1, Angle2, tin, Angle_out, tin_out)
REAL(SiKi) :: t_out ! Time to which to be extrap/interpd
REAL(R8Ki) :: Angle2_mod
-
+
+ ! If both inputs are the same, then the output must equal the input
+ if (Angle1 == Angle2) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
@@ -6490,7 +6514,13 @@ SUBROUTINE Angles_ExtrapInterp2_R4(Angle1, Angle2, Angle3, tin, Angle_out, tin_o
REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation
REAL(SiKi) :: Angle2_mod
REAL(SiKi) :: Angle3_mod
-
+
+ ! If all inputs are the same, then the output must equal the input
+ if ((Angle1 == Angle2) .and. (Angle2 == Angle3)) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
@@ -6553,7 +6583,13 @@ SUBROUTINE Angles_ExtrapInterp2_R8(Angle1, Angle2, Angle3, tin, Angle_out, tin_o
REAL(DbKi) :: scaleFactor ! temporary for extrapolation/interpolation
REAL(R8Ki) :: Angle2_mod
REAL(R8Ki) :: Angle3_mod
-
+
+ ! If all inputs are the same, then the output must equal the input
+ if ((Angle1 == Angle2) .and. (Angle2 == Angle3)) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
@@ -6616,7 +6652,13 @@ SUBROUTINE Angles_ExtrapInterp2_R4R(Angle1, Angle2, Angle3, tin, Angle_out, tin_
REAL(R8Ki) :: scaleFactor ! temporary for extrapolation/interpolation
REAL(SiKi) :: Angle2_mod
REAL(SiKi) :: Angle3_mod
-
+
+ ! If all inputs are the same, then the output must equal the input
+ if ((Angle1 == Angle2) .and. (Angle2 == Angle3)) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
@@ -6679,7 +6721,13 @@ SUBROUTINE Angles_ExtrapInterp2_R8R(Angle1, Angle2, Angle3, tin, Angle_out, tin_
REAL(R8Ki) :: scaleFactor ! temporary for extrapolation/interpolation
REAL(R8Ki) :: Angle2_mod
REAL(R8Ki) :: Angle3_mod
-
+
+ ! If all inputs are the same, then the output must equal the input
+ if ((Angle1 == Angle2) .and. (Angle2 == Angle3)) then
+ Angle_out = Angle1
+ return
+ end if
+
! we'll subtract a constant from the times to resolve some
! numerical issues when t gets large (and to simplify the equations)
t = tin - tin(1)
diff --git a/modules/openfast-library/src/FAST_Registry.txt b/modules/openfast-library/src/FAST_Registry.txt
index f1b4e5504f..b869f5202f 100644
--- a/modules/openfast-library/src/FAST_Registry.txt
+++ b/modules/openfast-library/src/FAST_Registry.txt
@@ -69,7 +69,7 @@ typedef ^ FAST_VTK_SurfaceType IntKi NWaveElevPts {2} - - "number of points for
typedef ^ FAST_VTK_SurfaceType SiKi WaveElevXY {:}{:} - - "X-Y locations for WaveElev output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number." "m,-"
typedef ^ FAST_VTK_SurfaceType SiKi WaveElev {:}{:} - - "wave elevation at WaveElevXY; first dimension is time step; second dimension is point number" "m,-"
typedef ^ FAST_VTK_SurfaceType FAST_VTK_BLSurfaceType BladeShape {:} - - "AirfoilCoords for each blade" m
-typedef ^ FAST_VTK_SurfaceType SiKi MorisonRad {:} - - "radius of each Morison node" m
+typedef ^ FAST_VTK_SurfaceType SiKi MorisonVisRad {:} - - "radius of each Morison node" m
typedef ^ FAST_VTK_ModeShapeType CHARACTER(1024) CheckpointRoot - - - "name of the checkpoint file written by FAST when linearization data was produced"
diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90
index 2f99a720cf..9129d0555d 100644
--- a/modules/openfast-library/src/FAST_Subs.f90
+++ b/modules/openfast-library/src/FAST_Subs.f90
@@ -783,6 +783,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD,
Init%InData_HD%TMax = p_FAST%TMax
Init%InData_HD%hasIce = p_FAST%CompIce /= Module_None
Init%InData_HD%Linearize = p_FAST%Linearize
+ if (p_FAST%WrVTK /= VTK_None) Init%InData_HD%VisMeshes=.true.
! these values support wave field handling
Init%InData_HD%WaveFieldMod = p_FAST%WaveFieldMod
@@ -1011,7 +1012,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD,
Init%InData_MD%Tmax = p_FAST%TMax ! expected simulation duration (used by MoorDyn for wave kinematics preprocesing)
Init%InData_MD%Linearize = p_FAST%Linearize
-
+ if (p_FAST%WrVTK /= VTK_None) Init%InData_MD%VisMeshes=.true.
CALL MD_Init( Init%InData_MD, MD%Input(1), MD%p, MD%x(STATE_CURR), MD%xd(STATE_CURR), MD%z(STATE_CURR), &
MD%OtherSt(STATE_CURR), MD%y, MD%m, p_FAST%dt_module( MODULE_MD ), Init%OutData_MD, ErrStat2, ErrMsg2 )
@@ -3339,6 +3340,9 @@ SUBROUTINE SetVTKParameters_B4HD(p_FAST, InitOutData_ED, InitInData_HD, BD, ErrS
if (ErrStat >= AbortErrLev) return
Width = p_FAST%VTK_Surface%GroundRad * VTK_GroundFactor
+!FIXME:ADP -- change test after merging to dev branch to compare to MHK_None
+ ! adjust to larger surface area for MHK since MHK turbines tend to be small compared to the platform
+ if (p_FAST%MHK /= 0_IntKi) Width = Width * 5.0_SiKi
dx = Width / (p_FAST%VTK_surface%NWaveElevPts(1) - 1)
dy = Width / (p_FAST%VTK_surface%NWaveElevPts(2) - 1)
@@ -3420,6 +3424,9 @@ SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_AD, InitInData_H
RefPoint = p_FAST%TurbinePos
if (p_FAST%CompHydro == MODULE_HD) then
RefLengths = p_FAST%VTK_Surface%GroundRad*VTK_GroundFactor/2.0_SiKi
+!FIXME: after merge to dev, change this test to use MHK_None
+ ! adjust to larger ground area for MHK since MHK turbines tend to be small compared to the platform
+ if (p_FAST%MHK /= 0_IntKi) RefLengths = RefLengths*4.0_SiKi
! note that p_FAST%TurbinePos(3) must be 0 for offshore turbines
RefPoint(3) = p_FAST%TurbinePos(3) - InitOutData_HD%WtrDpth
@@ -3556,10 +3563,8 @@ SUBROUTINE SetVTKParameters(p_FAST, InitOutData_ED, InitOutData_AD, InitInData_H
! morison surfaces
!.......................
- IF ( HD%Input(1)%Morison%Mesh%Committed ) THEN
- !TODO: FIX for visualization GJH 4/23/20
- ! call move_alloc(InitOutData_HD%Morison%Morison_Rad, p_FAST%VTK_Surface%MorisonRad)
-
+ IF ( HD%y%Morison%VisMesh%Committed ) THEN
+ call move_alloc(InitOutData_HD%Morison%MorisonVisRad, p_FAST%VTK_Surface%MorisonVisRad)
END IF
END SUBROUTINE SetVTKParameters
@@ -5649,7 +5654,10 @@ SUBROUTINE WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, H
IF ( p_FAST%CompHydro == Module_HD .and. allocated(HD%Input)) THEN
call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%PRPMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_PRP', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth )
call MeshWrVTK(p_FAST%TurbinePos, HD%y%WamitMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_WAMIT', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%WAMITMesh )
- call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%Mesh )
+ call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonPt', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%Mesh )
+ if (HD%y%Morison%VisMesh%Committed) then
+ call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%VisMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%Mesh )
+ endif
END IF
! SubDyn
@@ -5677,6 +5685,20 @@ SUBROUTINE WrVTK_AllMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM, H
call MeshWrVTK(p_FAST%TurbinePos, MD%y%CoupledLoads(1), trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFairlead', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, MD%Input(1)%CoupledKinematics(1) )
!call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%CoupledKinematics, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth )
end if
+ if (allocated(MD%y%VisLinesMesh)) then
+ do j=1,size(MD%y%VisLinesMesh)
+ if (MD%y%VisLinesMesh(j)%Committed) then
+ call MeshWrVTK(p_FAST%TurbinePos, MD%y%VisLinesMesh(j), trim(p_FAST%VTK_OutFileRoot)//'.MD_Line'//trim(Num2LStr(j)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrSTat2, ErrMsg2, p_FAST%VTK_tWidth )
+ endif
+ enddo
+ endif
+ if (allocated(MD%y%VisRodsMesh)) then
+ do j=1,size(MD%y%VisRodsMesh)
+ if (MD%y%VisRodsMesh(j)%Committed) then
+ call MeshWrVTK(p_FAST%TurbinePos, MD%y%VisRodsMesh(j), trim(p_FAST%VTK_OutFileRoot)//'.MD_Rod'//trim(Num2LStr(j)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrSTat2, ErrMsg2, p_FAST%VTK_tWidth )
+ endif
+ enddo
+ endif
! FEAMooring
ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN
@@ -5739,7 +5761,7 @@ SUBROUTINE WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM,
TYPE(IceFloe_Data), INTENT(IN ) :: IceF !< IceFloe data
TYPE(IceDyn_Data), INTENT(IN ) :: IceD !< All the IceDyn data used in time-step loop
- INTEGER(IntKi) :: NumBl, k
+ INTEGER(IntKi) :: NumBl, k, j
INTEGER(IntKi) :: ErrStat2
CHARACTER(ErrMsgLen) :: ErrMSg2
CHARACTER(*), PARAMETER :: RoutineName = 'WrVTK_BasicMeshes'
@@ -5799,16 +5821,35 @@ SUBROUTINE WrVTK_BasicMeshes(p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW, OpFM,
IF ( p_FAST%CompHydro == Module_HD .and. ALLOCATED(HD%Input)) THEN
call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%WAMITMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_WAMIT', y_FAST%VTK_count, &
p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%y%WAMITMesh )
- call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', y_FAST%VTK_count, &
+ call MeshWrVTK(p_FAST%TurbinePos, HD%Input(1)%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_MorisonPt', y_FAST%VTK_count, &
p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%y%Morison%Mesh )
+ if (HD%y%Morison%VisMesh%Committed) then
+ call MeshWrVTK(p_FAST%TurbinePos, HD%y%Morison%VisMesh, trim(p_FAST%VTK_OutFileRoot)//'.HD_Morison', y_FAST%VTK_count, &
+ p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, HD%Input(1)%Morison%Mesh )
+ endif
END IF
! Mooring Lines?
! IF ( p_FAST%CompMooring == Module_MAP ) THEN
! call MeshWrVTK(p_FAST%TurbinePos, MAPp%Input(1)%PtFairDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MAP_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth )
-! ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN
-! call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%CoupledKinematics, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth )
+ if ( p_FAST%CompMooring == Module_MD ) then
+ !call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%CoupledKinematics, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth )
+ if (allocated(MD%y%VisLinesMesh)) then
+ do j=1,size(MD%y%VisLinesMesh)
+ if (MD%y%VisLinesMesh(j)%Committed) then
+ call MeshWrVTK(p_FAST%TurbinePos, MD%y%VisLinesMesh(j), trim(p_FAST%VTK_OutFileRoot)//'.MD_Line'//trim(Num2LStr(j)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrSTat2, ErrMsg2, p_FAST%VTK_tWidth )
+ endif
+ enddo
+ endif
+ if (allocated(MD%y%VisRodsMesh)) then
+ do j=1,size(MD%y%VisRodsMesh)
+ if (MD%y%VisRodsMesh(j)%Committed) then
+ call MeshWrVTK(p_FAST%TurbinePos, MD%y%VisRodsMesh(j), trim(p_FAST%VTK_OutFileRoot)//'.MD_Rod'//trim(Num2LStr(j)), y_FAST%VTK_count, p_FAST%VTK_fields, ErrSTat2, ErrMsg2, p_FAST%VTK_tWidth )
+ endif
+ enddo
+ endif
+ endif
! ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN
! call MeshWrVTK(p_FAST%TurbinePos, FEAM%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'FEAM_PtFair_motion', y_FAST%VTK_count, p_FAST%VTK_fields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth )
! END IF
@@ -5843,7 +5884,7 @@ SUBROUTINE WrVTK_Surfaces(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW
logical, parameter :: OutputFields = .FALSE. ! due to confusion about what fields mean on a surface, we are going to just output the basic meshes if people ask for fields
- INTEGER(IntKi) :: NumBl, k
+ INTEGER(IntKi) :: NumBl, k, l
INTEGER(IntKi) :: ErrStat2
CHARACTER(ErrMsgLen) :: ErrMSg2
CHARACTER(*), PARAMETER :: RoutineName = 'WrVTK_Surfaces'
@@ -5916,26 +5957,38 @@ SUBROUTINE WrVTK_Surfaces(t_global, p_FAST, y_FAST, MeshMapData, ED, BD, AD, IfW
! call MeshWrVTK(p_FAST%TurbinePos, SD%y%y2Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_y2Mesh_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 )
! call MeshWrVTK(p_FAST%TurbinePos, SD%y%y3Mesh, trim(p_FAST%VTK_OutFileRoot)//'.SD_y3Mesh_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 )
! END IF
-!TODO: Fix below section for new Morison GJH 4/23/20
- !
- !IF ( HD%Input(1)%Morison%Mesh%Committed ) THEN
- ! !if ( p_FAST%CompSub == Module_NONE ) then ! floating
- ! ! OutputFields = .false.
- ! !else
- ! ! OutputFields = p_FAST%VTK_fields
- ! !end if
- !
- ! call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, HD%Input(1)%Morison%Mesh, trim(p_FAST%VTK_OutFileRoot)//'.MorisonSurface', &
- ! y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, p_FAST%VTK_Surface%NumSectors, &
- ! p_FAST%VTK_Surface%MorisonRad, Sib=HD%y%Morison%Mesh )
- !END IF
+
+
+! HydroDyn
+ IF ( HD%y%Morison%VisMesh%Committed ) THEN
+ call MeshWrVTK_Ln2Surface (p_FAST%TurbinePos, HD%y%Morison%VisMesh, trim(p_FAST%VTK_OutFileRoot)//'.MorisonSurface', &
+ y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2, p_FAST%VTK_tWidth, p_FAST%VTK_Surface%NumSectors, &
+ p_FAST%VTK_Surface%MorisonVisRad )
+ END IF
! Mooring Lines?
! IF ( p_FAST%CompMooring == Module_MAP ) THEN
! call MeshWrVTK(p_FAST%TurbinePos, MAPp%Input(1)%PtFairDisplacement, trim(p_FAST%VTK_OutFileRoot)//'.MAP_PtFair_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 )
-! ELSEIF ( p_FAST%CompMooring == Module_MD ) THEN
-! call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%CoupledKinematics, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 )
+ if ( p_FAST%CompMooring == Module_MD ) THEN
+ !call MeshWrVTK(p_FAST%TurbinePos, MD%Input(1)%CoupledKinematics, trim(p_FAST%VTK_OutFileRoot)//'.MD_PtFair_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 )
+ if (allocated(MD%y%VisLinesMesh)) then
+ do l=1,size(MD%y%VisLinesMesh)
+ if (MD%y%VisLinesMesh(l)%Committed) then ! No orientation data, so surface representation not possible
+ call MeshWrVTK(p_FAST%TurbinePos, MD%y%VisLinesMesh(l), trim(p_FAST%VTK_OutFileRoot)//'.MD_Line'//trim(Num2LStr(l)), y_FAST%VTK_count, p_FAST%VTK_fields, &
+ ErrSTat2, ErrMsg2, p_FAST%VTK_tWidth )
+ endif
+ enddo
+ endif
+ if (allocated(MD%y%VisRodsMesh)) then
+ do l=1,size(MD%y%VisRodsMesh)
+ if (MD%y%VisRodsMesh(l)%Committed) then ! No orientation data, so surface representation not possible
+ call MeshWrVTK_Ln2Surface(p_FAST%TurbinePos, MD%y%VisRodsMesh(l), trim(p_FAST%VTK_OutFileRoot)//'.MD_Rod'//trim(Num2LStr(l))//'Surface', y_FAST%VTK_count, p_FAST%VTK_fields, &
+ ErrSTat2, ErrMsg2, p_FAST%VTK_tWidth, NumSegments=p_FAST%VTK_Surface%NumSectors, Radius=MD%p%VisRodsDiam(l)%Diam )
+ endif
+ enddo
+ endif
+ endif
! ELSEIF ( p_FAST%CompMooring == Module_FEAM ) THEN
! call MeshWrVTK(p_FAST%TurbinePos, FEAM%Input(1)%PtFairleadDisplacement, trim(p_FAST%VTK_OutFileRoot)//'FEAM_PtFair_motion', y_FAST%VTK_count, OutputFields, ErrStat2, ErrMsg2 )
! END IF
@@ -6142,8 +6195,8 @@ SUBROUTINE WriteInputMeshesToFile(u_ED, u_AD, u_SD, u_HD, u_MAP, u_BD, FileName,
CALL MeshWrBin( unOut, u_ED%PlatformPtMesh, ErrStat, ErrMsg )
CALL MeshWrBin( unOut, u_SD%TPMesh, ErrStat, ErrMsg )
CALL MeshWrBin( unOut, u_SD%LMesh, ErrStat, ErrMsg )
- CALL MeshWrBin( unOut, u_HD%Morison%Mesh, ErrStat, ErrMsg )
- CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg )
+ CALL MeshWrBin( unOut, u_HD%Morison%Mesh, ErrStat, ErrMsg )
+ CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg )
CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg )
! Add how many BD blade meshes there are:
NumBl = SIZE(u_BD,1) ! Note that NumBl is B4Ki
@@ -6225,8 +6278,8 @@ SUBROUTINE WriteMotionMeshesToFile(time, y_ED, u_SD, y_SD, u_HD, u_MAP, y_BD, u_
CALL MeshWrBin( unOut, u_SD%TPMesh, ErrStat, ErrMsg )
CALL MeshWrBin( unOut, y_SD%y2Mesh, ErrStat, ErrMsg )
CALL MeshWrBin( unOut, y_SD%y3Mesh, ErrStat, ErrMsg )
- CALL MeshWrBin( unOut, u_HD%Morison%Mesh, ErrStat, ErrMsg )
- CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg )
+ CALL MeshWrBin( unOut, u_HD%Morison%Mesh, ErrStat, ErrMsg )
+ CALL MeshWrBin( unOut, u_HD%WAMITMesh, ErrStat, ErrMsg )
CALL MeshWrBin( unOut, u_MAP%PtFairDisplacement, ErrStat, ErrMsg )
DO K_local = 1,SIZE(y_BD,1)
CALL MeshWrBin( unOut, u_BD(K_local)%RootMotion, ErrStat, ErrMsg )
diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90
index afe11cb45c..fc8eac4b86 100644
--- a/modules/openfast-library/src/FAST_Types.f90
+++ b/modules/openfast-library/src/FAST_Types.f90
@@ -88,7 +88,7 @@ MODULE FAST_Types
REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElevXY !< X-Y locations for WaveElev output (for visualization). First dimension is the X (1) and Y (2) coordinate. Second dimension is the point number. [m,-]
REAL(SiKi) , DIMENSION(:,:), ALLOCATABLE :: WaveElev !< wave elevation at WaveElevXY; first dimension is time step; second dimension is point number [m,-]
TYPE(FAST_VTK_BLSurfaceType) , DIMENSION(:), ALLOCATABLE :: BladeShape !< AirfoilCoords for each blade [m]
- REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: MorisonRad !< radius of each Morison node [m]
+ REAL(SiKi) , DIMENSION(:), ALLOCATABLE :: MorisonVisRad !< radius of each Morison node [m]
END TYPE FAST_VTK_SurfaceType
! =======================
! ========= FAST_VTK_ModeShapeType =======
@@ -763,7 +763,7 @@ MODULE FAST_Types
CHARACTER(1024) :: RootName !< Root name of FAST output files (overrides normal operation) [-]
INTEGER(IntKi) :: NumActForcePtsBlade !< number of actuator line force points in blade [-]
INTEGER(IntKi) :: NumActForcePtsTower !< number of actuator line force points in tower [-]
- INTEGER(IntKi) :: NodeClusterType !< Node clustering for actuator line (0 - Uniform, 1 - Non-uniform clustered towards tip) [-]
+ LOGICAL :: NodeClusterType !< Node clustering for actuator line (0 - Uniform, 1 - Non-uniform clustered towards tip) [-]
END TYPE FAST_ExternInitType
! =======================
! ========= FAST_TurbineType =======
@@ -1084,17 +1084,17 @@ SUBROUTINE FAST_CopyVTK_SurfaceType( SrcVTK_SurfaceTypeData, DstVTK_SurfaceTypeD
IF (ErrStat>=AbortErrLev) RETURN
ENDDO
ENDIF
-IF (ALLOCATED(SrcVTK_SurfaceTypeData%MorisonRad)) THEN
- i1_l = LBOUND(SrcVTK_SurfaceTypeData%MorisonRad,1)
- i1_u = UBOUND(SrcVTK_SurfaceTypeData%MorisonRad,1)
- IF (.NOT. ALLOCATED(DstVTK_SurfaceTypeData%MorisonRad)) THEN
- ALLOCATE(DstVTK_SurfaceTypeData%MorisonRad(i1_l:i1_u),STAT=ErrStat2)
+IF (ALLOCATED(SrcVTK_SurfaceTypeData%MorisonVisRad)) THEN
+ i1_l = LBOUND(SrcVTK_SurfaceTypeData%MorisonVisRad,1)
+ i1_u = UBOUND(SrcVTK_SurfaceTypeData%MorisonVisRad,1)
+ IF (.NOT. ALLOCATED(DstVTK_SurfaceTypeData%MorisonVisRad)) THEN
+ ALLOCATE(DstVTK_SurfaceTypeData%MorisonVisRad(i1_l:i1_u),STAT=ErrStat2)
IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_SurfaceTypeData%MorisonRad.', ErrStat, ErrMsg,RoutineName)
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating DstVTK_SurfaceTypeData%MorisonVisRad.', ErrStat, ErrMsg,RoutineName)
RETURN
END IF
END IF
- DstVTK_SurfaceTypeData%MorisonRad = SrcVTK_SurfaceTypeData%MorisonRad
+ DstVTK_SurfaceTypeData%MorisonVisRad = SrcVTK_SurfaceTypeData%MorisonVisRad
ENDIF
END SUBROUTINE FAST_CopyVTK_SurfaceType
@@ -1135,8 +1135,8 @@ SUBROUTINE FAST_DestroyVTK_SurfaceType( VTK_SurfaceTypeData, ErrStat, ErrMsg, DE
ENDDO
DEALLOCATE(VTK_SurfaceTypeData%BladeShape)
ENDIF
-IF (ALLOCATED(VTK_SurfaceTypeData%MorisonRad)) THEN
- DEALLOCATE(VTK_SurfaceTypeData%MorisonRad)
+IF (ALLOCATED(VTK_SurfaceTypeData%MorisonVisRad)) THEN
+ DEALLOCATE(VTK_SurfaceTypeData%MorisonVisRad)
ENDIF
END SUBROUTINE FAST_DestroyVTK_SurfaceType
@@ -1219,10 +1219,10 @@ SUBROUTINE FAST_PackVTK_SurfaceType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat
END IF
END DO
END IF
- Int_BufSz = Int_BufSz + 1 ! MorisonRad allocated yes/no
- IF ( ALLOCATED(InData%MorisonRad) ) THEN
- Int_BufSz = Int_BufSz + 2*1 ! MorisonRad upper/lower bounds for each dimension
- Re_BufSz = Re_BufSz + SIZE(InData%MorisonRad) ! MorisonRad
+ Int_BufSz = Int_BufSz + 1 ! MorisonVisRad allocated yes/no
+ IF ( ALLOCATED(InData%MorisonVisRad) ) THEN
+ Int_BufSz = Int_BufSz + 2*1 ! MorisonVisRad upper/lower bounds for each dimension
+ Re_BufSz = Re_BufSz + SIZE(InData%MorisonVisRad) ! MorisonVisRad
END IF
IF ( Re_BufSz .GT. 0 ) THEN
ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 )
@@ -1363,18 +1363,18 @@ SUBROUTINE FAST_PackVTK_SurfaceType( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat
ENDIF
END DO
END IF
- IF ( .NOT. ALLOCATED(InData%MorisonRad) ) THEN
+ IF ( .NOT. ALLOCATED(InData%MorisonVisRad) ) THEN
IntKiBuf( Int_Xferred ) = 0
Int_Xferred = Int_Xferred + 1
ELSE
IntKiBuf( Int_Xferred ) = 1
Int_Xferred = Int_Xferred + 1
- IntKiBuf( Int_Xferred ) = LBOUND(InData%MorisonRad,1)
- IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MorisonRad,1)
+ IntKiBuf( Int_Xferred ) = LBOUND(InData%MorisonVisRad,1)
+ IntKiBuf( Int_Xferred + 1) = UBOUND(InData%MorisonVisRad,1)
Int_Xferred = Int_Xferred + 2
- DO i1 = LBOUND(InData%MorisonRad,1), UBOUND(InData%MorisonRad,1)
- ReKiBuf(Re_Xferred) = InData%MorisonRad(i1)
+ DO i1 = LBOUND(InData%MorisonVisRad,1), UBOUND(InData%MorisonVisRad,1)
+ ReKiBuf(Re_Xferred) = InData%MorisonVisRad(i1)
Re_Xferred = Re_Xferred + 1
END DO
END IF
@@ -1550,21 +1550,21 @@ SUBROUTINE FAST_UnPackVTK_SurfaceType( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrS
IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf)
END DO
END IF
- IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MorisonRad not allocated
+ IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! MorisonVisRad not allocated
Int_Xferred = Int_Xferred + 1
ELSE
Int_Xferred = Int_Xferred + 1
i1_l = IntKiBuf( Int_Xferred )
i1_u = IntKiBuf( Int_Xferred + 1)
Int_Xferred = Int_Xferred + 2
- IF (ALLOCATED(OutData%MorisonRad)) DEALLOCATE(OutData%MorisonRad)
- ALLOCATE(OutData%MorisonRad(i1_l:i1_u),STAT=ErrStat2)
+ IF (ALLOCATED(OutData%MorisonVisRad)) DEALLOCATE(OutData%MorisonVisRad)
+ ALLOCATE(OutData%MorisonVisRad(i1_l:i1_u),STAT=ErrStat2)
IF (ErrStat2 /= 0) THEN
- CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MorisonRad.', ErrStat, ErrMsg,RoutineName)
+ CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%MorisonVisRad.', ErrStat, ErrMsg,RoutineName)
RETURN
END IF
- DO i1 = LBOUND(OutData%MorisonRad,1), UBOUND(OutData%MorisonRad,1)
- OutData%MorisonRad(i1) = REAL(ReKiBuf(Re_Xferred), SiKi)
+ DO i1 = LBOUND(OutData%MorisonVisRad,1), UBOUND(OutData%MorisonVisRad,1)
+ OutData%MorisonVisRad(i1) = REAL(ReKiBuf(Re_Xferred), SiKi)
Re_Xferred = Re_Xferred + 1
END DO
END IF
diff --git a/modules/openfoam/CMakeLists.txt b/modules/openfoam/CMakeLists.txt
index c92947ccee..4e4cbd9885 100644
--- a/modules/openfoam/CMakeLists.txt
+++ b/modules/openfoam/CMakeLists.txt
@@ -18,10 +18,10 @@ if (GENERATE_TYPES)
generate_f90_types(src/OpenFOAM_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/OpenFOAM_Types.f90 -ccode)
endif()
-add_library(foamtypeslib src/OpenFOAM_Types.f90)
+add_library(foamtypeslib STATIC src/OpenFOAM_Types.f90)
target_link_libraries(foamtypeslib nwtclibs)
-add_library(foamfastlib src/OpenFOAM.f90)
+add_library(foamfastlib STATIC src/OpenFOAM.f90)
target_link_libraries(foamfastlib openfast_prelib)
target_include_directories(foamfastlib PUBLIC
$
diff --git a/modules/openfoam/src/OpenFOAM_Types.f90 b/modules/openfoam/src/OpenFOAM_Types.f90
index a3a92c86e5..3613f4b483 100644
--- a/modules/openfoam/src/OpenFOAM_Types.f90
+++ b/modules/openfoam/src/OpenFOAM_Types.f90
@@ -104,7 +104,7 @@ MODULE OpenFOAM_Types
REAL(KIND=C_FLOAT) :: BladeLength
REAL(KIND=C_FLOAT) :: TowerHeight
REAL(KIND=C_FLOAT) :: TowerBaseHeight
- LOGICAL(KIND=C_BOOL) :: NodeClusterType
+ INTEGER(KIND=C_INT) :: NodeClusterType
END TYPE OpFM_ParameterType_C
TYPE, PUBLIC :: OpFM_ParameterType
TYPE( OpFM_ParameterType_C ) :: C_obj
@@ -419,7 +419,7 @@ SUBROUTINE OpFM_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrM
Re_Xferred = Re_Xferred + 1
ReKiBuf(Re_Xferred) = InData%TowerBaseHeight
Re_Xferred = Re_Xferred + 1
- IntKiBuf(Int_Xferred) = TRANSFER(InData%NodeClusterType, IntKiBuf(1))
+ IntKiBuf(Int_Xferred) = InData%NodeClusterType
Int_Xferred = Int_Xferred + 1
END SUBROUTINE OpFM_PackInitInput
@@ -507,7 +507,7 @@ SUBROUTINE OpFM_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, E
OutData%TowerBaseHeight = ReKiBuf(Re_Xferred)
Re_Xferred = Re_Xferred + 1
OutData%C_obj%TowerBaseHeight = OutData%TowerBaseHeight
- OutData%NodeClusterType = TRANSFER(IntKiBuf(Int_Xferred), OutData%NodeClusterType)
+ OutData%NodeClusterType = IntKiBuf(Int_Xferred)
Int_Xferred = Int_Xferred + 1
OutData%C_obj%NodeClusterType = OutData%NodeClusterType
END SUBROUTINE OpFM_UnPackInitInput
@@ -1957,7 +1957,7 @@ SUBROUTINE OpFM_PackParam( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg,
Re_Xferred = Re_Xferred + 1
ReKiBuf(Re_Xferred) = InData%TowerBaseHeight
Re_Xferred = Re_Xferred + 1
- IntKiBuf(Int_Xferred) = TRANSFER(InData%NodeClusterType, IntKiBuf(1))
+ IntKiBuf(Int_Xferred) = InData%NodeClusterType
Int_Xferred = Int_Xferred + 1
END SUBROUTINE OpFM_PackParam
@@ -2060,7 +2060,7 @@ SUBROUTINE OpFM_UnPackParam( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMs
OutData%TowerBaseHeight = ReKiBuf(Re_Xferred)
Re_Xferred = Re_Xferred + 1
OutData%C_obj%TowerBaseHeight = OutData%TowerBaseHeight
- OutData%NodeClusterType = TRANSFER(IntKiBuf(Int_Xferred), OutData%NodeClusterType)
+ OutData%NodeClusterType = IntKiBuf(Int_Xferred)
Int_Xferred = Int_Xferred + 1
OutData%C_obj%NodeClusterType = OutData%NodeClusterType
END SUBROUTINE OpFM_UnPackParam
diff --git a/modules/servodyn/src/BladedInterface_EX.f90 b/modules/servodyn/src/BladedInterface_EX.f90
index 5775ffa6a3..4604a787fe 100644
--- a/modules/servodyn/src/BladedInterface_EX.f90
+++ b/modules/servodyn/src/BladedInterface_EX.f90
@@ -375,25 +375,33 @@ end subroutine InitStCCtrl
subroutine InitLidarMeas()
integer :: I,J
if (p%NumBeam == 0) return ! Nothing to set
- ! Allocate arrays for inputs
- if (allocated(InitInp%LidSpeed)) then ! make sure we have the array allocated before setting it
- CALL AllocAry(u%LidSpeed, size(InitInp%LidSpeed), 'u%LidSpeed', errStat2, ErrMsg2)
- if (Failed()) return
+ ! Allocate arrays for inputs -- these may have been set in ServoDyn already
+ if (allocated(InitInp%LidSpeed)) then ! make sure we have the array allocated before setting it
+ if (.not. allocated(u%LidSpeed)) then
+ CALL AllocAry(u%LidSpeed, size(InitInp%LidSpeed), 'u%LidSpeed', errStat2, ErrMsg2)
+ if (Failed()) return
+ endif
u%LidSpeed = InitInp%LidSpeed
endif
if (allocated(InitInp%MsrPositionsX)) then ! make sure we have the array allocated before setting it
- CALL AllocAry(u%MsrPositionsX, size(InitInp%MsrPositionsX), 'u%MsrPositionsX', errStat2, ErrMsg2)
- if (Failed()) return
+ if (.not. allocated(u%MsrPositionsX)) then
+ CALL AllocAry(u%MsrPositionsX, size(InitInp%MsrPositionsX), 'u%MsrPositionsX', errStat2, ErrMsg2)
+ if (Failed()) return
+ endif
u%MsrPositionsX = InitInp%MsrPositionsX
endif
if (allocated(InitInp%MsrPositionsY)) then ! make sure we have the array allocated before setting it
- CALL AllocAry(u%MsrPositionsY, size(InitInp%MsrPositionsY), 'u%MsrPositionsY', errStat2, ErrMsg2)
- if (Failed()) return
+ if (.not. allocated(u%MsrPositionsY)) then
+ CALL AllocAry(u%MsrPositionsY, size(InitInp%MsrPositionsY), 'u%MsrPositionsY', errStat2, ErrMsg2)
+ if (Failed()) return
+ endif
u%MsrPositionsY = InitInp%MsrPositionsY
endif
if (allocated(InitInp%MsrPositionsZ)) then ! make sure we have the array allocated before setting it
- CALL AllocAry(u%MsrPositionsZ, size(InitInp%MsrPositionsZ), 'u%MsrPositionsZ', errStat2, ErrMsg2)
- if (Failed()) return
+ if (.not. allocated(u%MsrPositionsZ)) then
+ CALL AllocAry(u%MsrPositionsZ, size(InitInp%MsrPositionsZ), 'u%MsrPositionsZ', errStat2, ErrMsg2)
+ if (Failed()) return
+ endif
u%MsrPositionsZ = InitInp%MsrPositionsZ
endif
! Write summary info to summary file
diff --git a/modules/wakedynamics/src/WakeDynamics.f90 b/modules/wakedynamics/src/WakeDynamics.f90
index afa31e4304..017d2e00e7 100644
--- a/modules/wakedynamics/src/WakeDynamics.f90
+++ b/modules/wakedynamics/src/WakeDynamics.f90
@@ -42,6 +42,7 @@ module WakeDynamics
public :: WD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating
! continuous states, and updating discrete states
public :: WD_CalcOutput ! Routine for computing outputs
+ public :: WD_WritePlaneOutputs ! Routine for IO Operation
public :: WD_CalcConstrStateResidual ! Tight coupling routine for returning the constraint state residual
public :: WD_TEST_Axi2Cart
@@ -427,7 +428,6 @@ subroutine WD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut
! Define parameters
!............................................................................................
p%TurbNum = InitInp%TurbNum
- p%OutFileRoot = InitInp%OutFileRoot
p%DT_low = interval
! Parameters from input file
p%Mod_Wake = InitInp%InputFileData%Mod_Wake
@@ -479,10 +479,9 @@ subroutine WD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut
end do
! Path for VTK outputs
- call GetPath( p%OutFileRoot, rootDir, baseName )
+ call GetPath( InitInp%OutFileRoot, rootDir, baseName )
+ p%OutFileRoot = baseName
p%OutFileVTKDir = trim(rootDir) // 'vtk_ff_planes'
-
-
p%filtParam = exp(-2.0_ReKi*pi*p%dt_low*InitInp%InputFileData%f_c)
p%oneMinusFiltParam = 1.0_ReKi - p%filtParam
@@ -1224,7 +1223,6 @@ subroutine AddSwirl(r, Vt_wake, y, z, Vy_curl, Vz_curl)
real(ReKi), dimension(:,:), intent(inout) :: Vy_curl !< Curl velocity in the y direction (m/s)
real(ReKi), dimension(:,:), intent(inout) :: Vz_curl !< Curl velocity in the z direction (m/s)
- real(ReKi) :: alpha
integer(IntKi) :: iz, iy, iLow, nr
real(ReKi) :: r_tmp, r_max
real(ReKi) :: Vt, S, C ! Sine and cosine
@@ -1257,9 +1255,7 @@ end subroutine AddSwirl
subroutine WD_TEST_AddVelocityCurl()
real(ReKi) :: Vy_curl(2,2)=0.0_ReKi
- real(ReKi) :: Vy_curl_ref(2,2)
real(ReKi) :: Vz_curl(2,2)=0.0_ReKi
- real(ReKi) :: Vz_curl_ref(2,2)
real(ReKi) :: y(2)=(/ 0., 2./)
real(ReKi) :: z(2)=(/-1.,1./)
real(ReKi) :: Gamma0
@@ -1287,7 +1283,6 @@ subroutine filter_angles2(psi_filt, chi_filt, psi, chi, alpha, alpha_bar)
real(ReKi), intent(in) :: chi !< skew angle
real(ReKi), intent(in) :: alpha !< filter weight
real(ReKi), intent(in) :: alpha_bar !< 1-alpha
- real(ReKi) :: t_filt !< output
real(ReKi) :: x,y
real(ReKi) :: lambda(3,2)
real(ReKi) :: theta_out(3)
@@ -1391,7 +1386,6 @@ subroutine Axisymmetric2CartesianVx(Vx_axi, r, y, z, Vx)
real(ReKi), dimension(:,:), intent(inout) :: Vx !< Axial velocity, distributed across the plane (m/s)
integer(IntKi) :: iz, iy, nr, iLow
real(ReKi) :: r_tmp, r_max
- real(ReKi) :: Vr, S, C ! Sine and cosine
nr = size(r)
r_max = r(nr)
do iz = 1,size(z)
@@ -1498,16 +1492,12 @@ subroutine WD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg )
CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None
- integer, parameter :: indx = 1
integer(intKi) :: n, i, iy, iz, maxPln
integer(intKi) :: ErrStat2
character(ErrMsgLen) :: ErrMsg2
character(*), parameter :: RoutineName = 'WD_CalcOutput'
real(ReKi) :: correction(3)
real(ReKi) :: C, S, dvdr, dvdtheta_r, R, r_tmp
- character(1024) :: Filename
- type(VTK_Misc) :: mvtk
- real(ReKi), dimension(3) :: dx
errStat = ErrID_None
errMsg = ""
@@ -1550,7 +1540,10 @@ subroutine WD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg )
! Misc approx
m%Ct_avg = get_Ctavg(p%r, u%Ct_azavg, u%D_rotor)
m%GammaCurl = u%D_Rotor/2. * u%Vx_wind_disk * m%Ct_avg * sin(u%chi_skew) * cos(u%chi_skew)
-
+
+ if ( p%OutAllPlanes ) then
+ call mkdir(p%OutFileVTKDir)
+ endif
else
y%x_plane = xd%x_plane
@@ -1616,13 +1609,40 @@ subroutine WD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg )
end if
+end subroutine WD_CalcOutput
+
+!----------------------------------------------------------------------------------------------------------------------------------
+!>
+subroutine WD_WritePlaneOutputs( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg )
+ use VTK !
+ REAL(DbKi), INTENT(IN ) :: t !< Current simulation time in seconds
+ TYPE(WD_InputType), INTENT(IN ) :: u !< Inputs at Time t
+ TYPE(WD_ParameterType), INTENT(IN ) :: p !< Parameters
+ TYPE(WD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t
+ TYPE(WD_DiscreteStateType), INTENT(IN ) :: xd !< Discrete states at t
+ TYPE(WD_ConstraintStateType), INTENT(IN ) :: z !< Constraint states at t
+ TYPE(WD_OtherStateType), INTENT(IN ) :: OtherState !< Other states at t
+ TYPE(WD_OutputType), INTENT(IN ) :: y !< Outputs computed at t (Input only so that mesh con-
+ type(WD_MiscVarType), intent(IN ) :: m !< Misc/optimization variables
+ INTEGER(IntKi), INTENT( OUT) :: errStat !< Error status of the operation
+ CHARACTER(*), INTENT( OUT) :: errMsg !< Error message if errStat /= ErrID_None
+ integer(intKi) :: n, i
+ integer(intKi) :: ErrStat2
+ character(ErrMsgLen) :: ErrMsg2
+ character(*), parameter :: RoutineName = 'WD_WritePlaneOutputs'
+ real(ReKi) :: correction(3)
+ character(1024) :: Filename
+ type(VTK_Misc) :: mvtk
+ real(ReKi), dimension(3) :: dx
+ real(ReKi), dimension(3) :: x0
+ errStat = ErrID_None
+ errMsg = ""
+
+ n = nint(t/p%DT_low)
! --- VTK outputs per plane
if (p%OutAllPlanes) then
call vtk_misc_init(mvtk)
call set_vtk_binary_format(.false., mvtk)
- if ( OtherState%firstPass ) then
- call MKDIR(p%OutFileVTKDir)
- endif
do i = 0, min(n-1,p%NumPlanes-1), 1
! if (EqualRealNos(t,0.0_DbKi) ) then
! write(Filename,'(A,I4.4,A)') trim(p%OutFileVTKDir)//'/PlaneOutputsAtPlane_',i,'_Init.vtk'
@@ -1647,11 +1667,14 @@ subroutine WD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg )
dx(1) = 0.0
dx(2) = p%dr
dx(3) = p%dr
- call vtk_dataset_structured_points((/xd%p_plane(1,i),-dx*p%NumRadii,-dx*p%NumRadii/),dx,(/1,p%NumRadii*2-1,p%NumRadii*2-1/),mvtk)
+ x0(1) = xd%p_plane(1,i)
+ x0(2) = xd%p_plane(2,i) - p%dr*p%NumRadii
+ x0(3) = xd%p_plane(3,i) - p%dr*p%NumRadii
+ call vtk_dataset_structured_points(x0, dx, (/1,p%NumRadii*2-1,p%NumRadii*2-1/),mvtk)
call vtk_point_data_init(mvtk)
- call vtk_point_data_scalar(xd%Vx_wake2(:,:,i),'Vx',mvtk)
- call vtk_point_data_scalar(xd%Vy_wake2(:,:,i),'Vy',mvtk)
- call vtk_point_data_scalar(xd%Vz_wake2(:,:,i),'Vz',mvtk)
+ call vtk_point_data_scalar(y%Vx_wake2(:,:,i),'Vx',mvtk)
+ call vtk_point_data_scalar(y%Vy_wake2(:,:,i),'Vy',mvtk)
+ call vtk_point_data_scalar(y%Vz_wake2(:,:,i),'Vz',mvtk)
call vtk_point_data_scalar(m%vt_amb2(:,:,i),'vt_amb2', mvtk)
call vtk_point_data_scalar(m%vt_shr2(:,:,i),'vt_shr2', mvtk)
call vtk_point_data_scalar(m%vt_tot2(:,:,i),'vt_tot2', mvtk)
@@ -1664,11 +1687,14 @@ subroutine WD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg )
call vtk_point_data_scalar(y%WAT_k_mt(:,:,i),'k_mt', mvtk)
endif
call vtk_close_file(mvtk)
+ else
+ call SetErrStat(ErrID_Fatal, '[INFO] Failed to write: '//trim(filename), errStat, errMsg, RoutineName)
endif
enddo ! loop on planes
endif
-end subroutine WD_CalcOutput
+end subroutine WD_WritePlaneOutputs
+
!----------------------------------------------------------------------------------------------------------------------------------
!> Tight coupling routine for solving for the residual of the constraint state equations
@@ -1691,10 +1717,10 @@ subroutine WD_CalcConstrStateResidual( Time, u, p, x, xd, z, OtherState, m, z_re
! Local variables
- integer, parameter :: indx = 1
- integer(intKi) :: ErrStat2
- character(ErrMsgLen) :: ErrMsg2
- character(*), parameter :: RoutineName = 'WD_CalcConstrStateResidual'
+ !integer, parameter :: indx = 1
+ !integer(intKi) :: ErrStat2
+ !character(ErrMsgLen) :: ErrMsg2
+ !character(*), parameter :: RoutineName = 'WD_CalcConstrStateResidual'
@@ -1779,8 +1805,6 @@ SUBROUTINE ValidateInitInputData( DT_low, InitInp, InputFileData, errStat, errMs
! local variables
- integer(IntKi) :: k ! Blade number
- integer(IntKi) :: j ! node number
character(*), parameter :: RoutineName = 'ValidateInitInputData'
errStat = ErrID_None
diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake
index 0e04de8a9f..3c4588f3b0 100644
--- a/reg_tests/CTestList.cmake
+++ b/reg_tests/CTestList.cmake
@@ -282,6 +282,7 @@ of_regression("EllipticalWing_OLAF" "openfast;aerodyn15;olaf"
of_regression("StC_test_OC4Semi" "openfast;servodyn;hydrodyn;moordyn;offshore;stc")
of_regression("MHK_RM1_Fixed" "openfast;elastodyn;aerodyn15;mhk")
of_regression("MHK_RM1_Floating" "openfast;elastodyn;aerodyn15;hydrodyn;moordyn;mhk")
+of_regression("Tailfin_FreeYaw1DOF_PolarBased" "openfast;elastodyn;aerodyn15")
# OpenFAST C++ API test
if(BUILD_OPENFAST_CPP_API)
@@ -306,6 +307,8 @@ of_regression_py("EllipticalWing_OLAF_py" "openfast;fastlib;p
of_regression_aeroacoustic("IEA_LB_RWT-AeroAcoustics" "openfast;aerodyn15;aeroacoustics")
# Linearized OpenFAST regression tests
+# of_regression_linear("Fake5MW_AeroLin_B1_UA4_DBEMT3" "openfast;linear;elastodyn") #Also: aerodyn
+of_regression_linear("Fake5MW_AeroLin_B3_UA6" "openfast;linear;elastodyn") #Also: aerodyn
of_regression_linear("WP_Stationary_Linear" "openfast;linear;elastodyn")
of_regression_linear("Ideal_Beam_Fixed_Free_Linear" "openfast;linear;beamdyn")
of_regression_linear("Ideal_Beam_Free_Free_Linear" "openfast;linear;beamdyn")
@@ -386,6 +389,7 @@ ifw_regression("ifw_uniform" "inflowwind")
ifw_regression("ifw_nativeBladed" "inflowwind")
ifw_regression("ifw_BoxExceed" "inflowwind")
ifw_regression("ifw_BoxExceedTwr" "inflowwind")
+ifw_regression("ifw_HAWC" "inflowwind")
# Py-InflowWind regression tests
py_ifw_regression("py_ifw_turbsimff" "inflowwind;python")
diff --git a/reg_tests/executeInflowwindRegressionCase.py b/reg_tests/executeInflowwindRegressionCase.py
index 3979d641c8..fd940feec7 100644
--- a/reg_tests/executeInflowwindRegressionCase.py
+++ b/reg_tests/executeInflowwindRegressionCase.py
@@ -94,6 +94,7 @@
os.makedirs(testBuildDirectory)
for file in (glob.glob(os.path.join(inputsDirectory,"*.inp")) +
glob.glob(os.path.join(inputsDirectory,"*.bts"))+
+ glob.glob(os.path.join(inputsDirectory,"*.bin"))+
glob.glob(os.path.join(inputsDirectory,"*.wnd"))+
glob.glob(os.path.join(inputsDirectory,"*.hh"))+
glob.glob(os.path.join(inputsDirectory,"*.sum"))):
diff --git a/reg_tests/executeOpenfastLinearRegressionCase.py b/reg_tests/executeOpenfastLinearRegressionCase.py
index 4eed9f259e..2e88bd67e4 100644
--- a/reg_tests/executeOpenfastLinearRegressionCase.py
+++ b/reg_tests/executeOpenfastLinearRegressionCase.py
@@ -30,13 +30,16 @@
import numpy as np
import shutil
import subprocess
+from eva import eigA, eig
import rtestlib as rtl
import openfastDrivers
import pass_fail
from errorPlotting import exportCaseSummary
+from fast_linearization_file import FASTLinearizationFile
+# from weio.fast_linearization_file import FASTLinearizationFile
##### Helper functions
-excludeExt=['.out','.outb','.ech','.yaml','.sum','.log']
+excludeExt=['.out','.outb','.ech','.yaml','.sum','.log','.md']
def file_line_count(filename):
file_handle = open(filename, 'r')
@@ -45,8 +48,8 @@ def file_line_count(filename):
file_handle.close()
return i + 1
-def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
- return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
+def isclose(a, b, rtol=1e-09, atol=0.0):
+ return abs(a-b) <= max(rtol * max(abs(a), abs(b)), atol)
##### Main program
@@ -77,12 +80,32 @@ def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
noExec = args.noExec
verbose = args.verbose
-# Tolerance have not been tuned for linearization case outputs.
-# This is using 1e-5 since that seemed like a decent value prior to
-# switching to relative and absolute tolerance.
-rtol = 1e-5
+# --- Tolerances for matrix comparison
+# Outputs of lin matrices have 3 decimal digits leading to minimum error of 0.001
+# Therefore the relative error to detect a change in the third decimal place
+# is between 1e-3 and 1e-4. We allow a bit of margin and use rtol=2e-3
+# Lin matrices have a lot of small values, so atol is quite important
+rtol = 2e-3
atol = 1e-5
+# --- Tolerances for frequencies
+# Low frequencies are hard to match, so we use a high atol
+rtol_f=1e-2
+atol_f=1e-2
+
+# --- Tolerances for damping
+# damping ratio is in [%] so we relax the atol
+rtol_d=1e-2
+atol_d=1e-1
+
+
+CasePrefix=' Case: {}: '.format(caseName)
+def exitWithError(msg):
+ rtl.exitWithError(CasePrefix+msg)
+def indent(msg, sindent='\t'):
+ return '\n'.join([sindent+s for s in msg.split('\n')])
+
+
# validate inputs
rtl.validateExeOrExit(executable)
rtl.validateDirOrExit(sourceDirectory)
@@ -100,11 +123,11 @@ def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
# verify all the required directories exist
if not os.path.isdir(rtest):
- rtl.exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest))
+ exitWithError("The test data directory, {}, does not exist. If you haven't already, run `git submodule update --init --recursive`".format(rtest))
if not os.path.isdir(targetOutputDirectory):
- rtl.exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory))
+ exitWithError("The test data outputs directory, {}, does not exist. Try running `git submodule update`".format(targetOutputDirectory))
if not os.path.isdir(inputsDirectory):
- rtl.exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory))
+ exitWithError("The test data inputs directory, {}, does not exist. Verify your local repository is up to date.".format(inputsDirectory))
# create the local output directory if it does not already exist
# and initialize it with input files for all test cases
@@ -130,9 +153,10 @@ def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
rtl.copyTree(srcname, dstname, excludeExt=excludeExt)
else:
shutil.copy2(srcname, dstname)
-
-if not os.path.isdir(testBuildDirectory):
- rtl.copyTree(inputsDirectory, testBuildDirectory, excludeExt=excludeExt)
+#
+# Copying the actual test directory
+# if not os.path.isdir(testBuildDirectory):
+rtl.copyTree(inputsDirectory, testBuildDirectory, excludeExt=excludeExt, renameExtDict={'.lin':'.ref_lin'})
### Run openfast on the test case
if not noExec:
@@ -143,108 +167,140 @@ def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
### Get a all the .lin files in the baseline directory
baselineOutFiles = [f for f in os.listdir(targetOutputDirectory) if '.lin' in f]
+if len(baselineOutFiles)==0:
+ exitWithError("No lin files present in baseline.")
+
# these should all exist in the local outputs directory
localFiles = os.listdir(testBuildDirectory)
localOutFiles = [f for f in localFiles if f in baselineOutFiles]
if len(localOutFiles) != len(baselineOutFiles):
- print("Error in case {}: an expected local solution file does not exist.".format(caseName))
- sys.exit(1)
-
-### test for regression
-for i, f in enumerate(localOutFiles):
- local_file = os.path.join(testBuildDirectory, f)
- baseline_file = os.path.join(targetOutputDirectory, f)
-
- # verify both files have the same number of lines
- local_file_line_count = file_line_count(local_file)
- baseline_file_line_count = file_line_count(baseline_file)
- if local_file_line_count != baseline_file_line_count:
- print("Error in case {}: local and baseline solutions have different line counts in".format(caseName))
- print("\t{}".format(local_file))
- print("\t{}".format(baseline_file))
- sys.exit(1)
-
- # open both files
- local_handle = open(local_file, 'r')
- baseline_handle = open(baseline_file, 'r')
-
- # parse the files
-
- # skip the first 6 lines since they are headers and may change without conseequence
- for i in range(6):
- baseline_handle.readline()
- local_handle.readline()
-
- # the next 10 lines are simulation info; save what we need
- for i in range(11):
- b_line = baseline_handle.readline()
- l_line = local_handle.readline()
- if i == 5:
- b_num_continuous_states = int(b_line.split()[-1])
- l_num_continuous_states = int(l_line.split()[-1])
- elif i == 8:
- b_num_inputs = int(b_line.split()[-1])
- l_num_inputs = int(l_line.split()[-1])
- elif i == 9:
- b_num_outputs = int(b_line.split()[-1])
- l_num_outputs = int(l_line.split()[-1])
-
- # find the "Jacobian matrices:" line
- for i in range(local_file_line_count):
- b_line = baseline_handle.readline()
- l_line = local_handle.readline()
- if "Jacobian matrices:" in l_line:
- break
-
- # skip 1 empty/header lines
- for i in range(1):
- baseline_handle.readline()
- local_handle.readline()
-
- # read and compare Jacobian matrices
- for i in range(local_file_line_count):
- b_line = baseline_handle.readline()
- l_line = local_handle.readline()
- if ":" in l_line:
- continue
- if len(l_line) < 5:
- break
- b_elements = b_line.split()
- l_elements = l_line.split()
- for j, l_element in enumerate(l_elements):
- l_float = float(l_element)
- b_float = float(b_elements[j])
- if not isclose(l_float, b_float, rtol, atol):
- print(f"Failed in Jacobian matrix comparison:")
- print(f"{l_float} in {local_file}")
- print(f"{b_float} in {baseline_file}")
- sys.exit(1)
-
- # skip 2 empty/header lines
- for i in range(2):
- baseline_handle.readline()
- local_handle.readline()
-
- # read and compare Linearized state matrices
- for i in range(local_file_line_count):
- b_line = baseline_handle.readline()
- l_line = local_handle.readline()
- if ":" in l_line:
- continue
- if len(l_line) < 5:
- break
- b_elements = b_line.split()
- l_elements = l_line.split()
- for j, l_element in enumerate(l_elements):
- l_float = float(l_element)
- b_float = float(b_elements[j])
- if not isclose(l_float, b_float, rtol, atol):
- print(f"Failed in state matrix comparison: {l_float} and {b_float}")
- sys.exit(1)
-
- local_handle.close()
- baseline_handle.close()
+ exitWithError("An expected local solution file does not exist:")
+
+### test for regression (compare lin files only)
+try:
+ for i, f in enumerate(localOutFiles):
+ local_file = os.path.join(testBuildDirectory, f)
+ baseline_file = os.path.join(targetOutputDirectory, f)
+ if verbose:
+ print(CasePrefix+'ref:', baseline_file)
+ print(CasePrefix+'new:', local_file)
+
+ # verify both files have the same number of lines
+ local_file_line_count = file_line_count(local_file)
+ baseline_file_line_count = file_line_count(baseline_file)
+ if local_file_line_count != baseline_file_line_count:
+ Err="Local and baseline solutions have different line counts in"
+ Err+="\n\tFile1:{}".format(local_file)
+ Err+="\n\tFile2:{}\n\n".format(baseline_file)
+ raise Exception(Err)
+
+ # open both files
+ floc = FASTLinearizationFile(local_file)
+ fbas = FASTLinearizationFile(baseline_file)
+
+ # --- Test that they have the same variables
+ kloc = floc.keys()
+ kbas = fbas.keys()
+ try:
+ np.testing.assert_equal(kloc, kbas)
+ except Exception as e:
+ Err = 'Different keys in local linfile.\n'
+ Err+= '\tNew:{}\n'.format(kloc)
+ Err+= '\tRef:{}\n'.format(kbas)
+ Err+= '\tin linfile: {}.\n'.format(local_file)
+ raise Exception(Err)
+
+ # --- Compare 10 first frequencies and damping ratios in 'A' matrix
+ if 'A' in fbas.keys():
+ Abas = fbas['A']
+ Aloc = floc['A']
+ # Note: we could potentially reorder states like MBC does, but no need for freq/damping
+ _, zeta_bas, _, freq_bas = eigA(Abas, nq=None, nq1=None, sort=True)
+ _, zeta_loc, _, freq_loc = eigA(Aloc, nq=None, nq1=None, sort=True)
+
+ if len(freq_bas)==0:
+ # We use complex eigenvalues instead of frequencies/damping
+ # If this fails often, we should discard this test.
+ _, Lambda = eig(Abas, sort=False)
+ v_bas = np.diag(Lambda)
+ _, Lambda = eig(Aloc, sort=False)
+ v_loc = np.diag(Lambda)
+
+ if verbose:
+ print(CasePrefix+'val_ref:', v_bas[:7])
+ print(CasePrefix+'val_new:', v_loc[:7])
+ try:
+ np.testing.assert_allclose(v_bas[:10], v_loc[:10], rtol=rtol_f, atol=atol_f)
+ except Exception as e:
+ raise Exception('Failed to compare A-matrix frequencies\n\tLinfile: {}.\n\tException: {}'.format(local_file, indent(e.args[0])))
+ else:
+
+ #if verbose:
+ print(CasePrefix+'freq_ref:', np.around(freq_bas[:8] ,5), '[Hz]')
+ print(CasePrefix+'freq_new:', np.around(freq_loc[:8] ,5),'[Hz]')
+ print(CasePrefix+'damp_ref:', np.around(zeta_bas[:8]*100,5), '[%]')
+ print(CasePrefix+'damp_new:', np.around(zeta_loc[:8]*100,5), '[%]')
+
+ try:
+ np.testing.assert_allclose(freq_loc[:10], freq_bas[:10], rtol=rtol_f, atol=atol_f)
+ except Exception as e:
+ raise Exception('Failed to compare A-matrix frequencies\n\tLinfile: {}.\n\tException: {}'.format(local_file, indent(e.args[0])))
+
+
+ if caseName=='Ideal_Beam_Free_Free_Linear':
+ # The free-free case is a bit weird, smae frequencies but dampings are +/- a value
+ zeta_loc=np.abs(zeta_loc)
+ zeta_bas=np.abs(zeta_bas)
+
+
+ try:
+ # Note: damping ratios in [%]
+ np.testing.assert_allclose(zeta_loc[:10]*100, zeta_bas[:10]*100, rtol=rtol_d, atol=atol_d)
+ except Exception as e:
+ raise Exception('Failed to compare A-matrix damping ratios\n\tLinfile: {}.\n\tException: {}'.format(local_file, indent(e.args[0])))
+
+
+
+ # --- Compare individual matrices/vectors
+ KEYS= ['A','B','C','D','dUdu','dUdy']
+ KEYS+=['x','y','u','xdot']
+ for k,v in fbas.items():
+ if k in KEYS and v is not None:
+ if verbose:
+ print(CasePrefix+'key:', k)
+ # Arrays
+ Mloc=np.atleast_2d(floc[k])
+ Mbas=np.atleast_2d(fbas[k])
+
+ # --- Compare dimensions
+ try:
+ np.testing.assert_equal(Mloc.shape, Mbas.shape)
+ except Exception as e:
+ Err = 'Different dimensions for variable `{}`.\n'.format(k)
+ Err+= '\tNew:{}\n'.format(Mloc.shape)
+ Err+= '\tRef:{}\n'.format(Mbas.shape)
+ Err+= '\tLinfile: {}.\n'.format(local_file)
+ raise Exception(Err)
+
+
+ # We for loop below to get the first element that mismatch
+ # Otherwise, do: np.testing.assert_allclose(floc[k], fbas[k], rtol=rtol, atol=atol)
+ for i in range(Mbas.shape[0]):
+ for j in range(Mbas.shape[1]):
+ # Old method:
+ #if not isclose(Mloc[i,j], Mbas[i,j], rtol=rtol, atol=atol):
+ # sElem = 'Element [{},{}], new : {}, baseline: {}'.format(i+1,j+1,Mloc[i,j], Mbas[i,j])
+ # raise Exception('Failed to compare variable `{}`, {} \n\tLinfile: {}.'.format(k, sElem, local_file)) #, e.args[0]))
+ try:
+ np.testing.assert_allclose(Mloc[i,j], Mbas[i,j], rtol=rtol, atol=atol)
+ except Exception as e:
+ sElem = 'Element [{},{}], new : {}, baseline: {}'.format(i+1,j+1,Mloc[i,j], Mbas[i,j])
+ raise Exception('Failed to compare variable `{}`, {} \n\tLinfile: {}.\n\tException: {}'.format(k, sElem, local_file, indent(e.args[0])))
+
+except Exception as e:
+ exitWithError(e.args[0])
# passing case
sys.exit(0)
+
diff --git a/reg_tests/executeOpenfastRegressionCase.py b/reg_tests/executeOpenfastRegressionCase.py
index a0cae63e6b..c4aa6c23a2 100644
--- a/reg_tests/executeOpenfastRegressionCase.py
+++ b/reg_tests/executeOpenfastRegressionCase.py
@@ -93,7 +93,7 @@
# create the local output directory if it does not already exist
# and initialize it with input files for all test cases
-for data in ["AOC", "AWT27", "SWRT", "UAE_VI", "WP_Baseline"]:
+for data in ["AOC", "AWT27", "_DummyTurbineData", "SWRT", "UAE_VI", "WP_Baseline"]:
dataDir = os.path.join(buildDirectory, data)
if not os.path.isdir(dataDir):
rtl.copyTree(os.path.join(moduleDirectory, data), dataDir, excludeExt=excludeExt)
diff --git a/reg_tests/lib/eva.py b/reg_tests/lib/eva.py
new file mode 100644
index 0000000000..3908729b94
--- /dev/null
+++ b/reg_tests/lib/eva.py
@@ -0,0 +1,334 @@
+"""
+Taken from python-toolbox https://github.com/openfast/python-toolbox
+
+Eigenvalue analyses (EVA) tools for:
+ - arbitrary systems: system matrix (A)
+ - and mechnical systems: mass (M), stiffness (K) and damping (C) matrices
+
+Some definitions:
+
+ - zeta: damping ratio
+
+ - delta/log_dec: logarithmic decrement
+
+ - xi: approximation of logarithmic decrement: xi = 2 pi zeta
+
+ - omega0 : natural frequency
+
+ - omega_d : damped frequency omega_d = omega_0 sqrt(1-zeta^2)
+
+
+"""
+import pandas as pd
+import numpy as np
+# from scipy import linalg
+from numpy import linalg
+
+def polyeig(*A, sort=False, normQ=None):
+ """
+ Solve the polynomial eigenvalue problem:
+ (A0 + e A1 +...+ e**p Ap)x = 0
+
+ Return the eigenvectors [x_i] and eigenvalues [e_i] that are solutions.
+
+ Usage:
+ X,e = polyeig(A0,A1,..,Ap)
+
+ Most common usage, to solve a second order system: (K + C e + M e**2) x =0
+ X,e = polyeig(K,C,M)
+
+ """
+ if len(A)<=0:
+ raise Exception('Provide at least one matrix')
+ for Ai in A:
+ if Ai.shape[0] != Ai.shape[1]:
+ raise Exception('Matrices must be square')
+ if Ai.shape != A[0].shape:
+ raise Exception('All matrices must have the same shapes');
+
+ n = A[0].shape[0]
+ l = len(A)-1
+ # Assemble matrices for generalized problem
+ C = np.block([
+ [np.zeros((n*(l-1),n)), np.eye(n*(l-1))],
+ [-np.column_stack( A[0:-1])]
+ ])
+ D = np.block([
+ [np.eye(n*(l-1)), np.zeros((n*(l-1), n))],
+ [np.zeros((n, n*(l-1))), A[-1] ]
+ ]);
+ # Solve generalized eigenvalue problem
+ e, X = linalg.eig(C, D);
+ if np.all(np.isreal(e)):
+ e=np.real(e)
+ X=X[:n,:]
+
+ # Sort eigen values
+ if sort:
+ I = np.argsort(e)
+ X = X[:,I]
+ e = e[I]
+
+ # Scaling each mode by max
+ if normQ=='byMax':
+ X /= np.tile(np.max(np.abs(X),axis=0), (n,1))
+
+ return X, e
+
+
+def eig(K, M=None, freq_out=False, sort=True, normQ=None, discardIm=False, massScaling=True):
+ """ performs eigenvalue analysis and return same values as matlab
+
+ returns:
+ Q : matrix of column eigenvectors
+ Lambda: matrix where diagonal values are eigenvalues
+ frequency = np.sqrt(np.diag(Lambda))/(2*np.pi)
+ or
+ frequencies (if freq_out is True)
+ """
+ if M is not None:
+ D,Q = linalg.eig(K,M)
+ # --- rescaling using mass matrix to be consistent with Matlab
+ # TODO, this can be made smarter
+ # TODO this should be a normQ
+ if massScaling:
+ for j in range(M.shape[1]):
+ q_j = Q[:,j]
+ modalmass_j = np.dot(q_j.T,M).dot(q_j)
+ Q[:,j]= Q[:,j]/np.sqrt(modalmass_j)
+ Lambda=np.dot(Q.T,K).dot(Q)
+ else:
+ D,Q = linalg.eig(K)
+ Lambda = np.diag(D)
+
+ # --- Sort
+ lambdaDiag=np.diag(Lambda)
+ if sort:
+ I = np.argsort(lambdaDiag)
+ Q = Q[:,I]
+ lambdaDiag = lambdaDiag[I]
+ if freq_out:
+ Lambda = np.sqrt(lambdaDiag)/(2*np.pi) # frequencies [Hz]
+ else:
+ Lambda = np.diag(lambdaDiag) # enforcing purely diagonal
+
+ # --- Renormalize modes if users wants to
+ if normQ == 'byMax':
+ for j in range(Q.shape[1]):
+ q_j = Q[:,j]
+ iMax = np.argmax(np.abs(q_j))
+ scale = q_j[iMax] # not using abs to normalize to "1" and not "+/-1"
+ Q[:,j]= Q[:,j]/scale
+
+ # --- Sanitization, ensure real values
+ if discardIm:
+ Q_im = np.imag(Q)
+ Q = np.real(Q)
+ imm = np.mean(np.abs(Q_im),axis = 0)
+ bb = imm>0
+ if sum(bb)>0:
+ W=list(np.where(bb)[0])
+ print('[WARN] Found {:d} complex eigenvectors at positions {}/{}'.format(sum(bb),W,Q.shape[0]))
+ Lambda = np.real(Lambda)
+
+ return Q,Lambda
+
+
+def eigA(A, nq=None, nq1=None, fullEV=False, normQ=None, sort=True):
+ """
+ Perform eigenvalue analysis on a "state" matrix A
+ where states are assumed to be ordered as {q, q_dot, q1}
+ This order is only relevant for returning the eigenvectors.
+
+ INPUTS:
+ - A : square state matrix
+ - nq: number of second order states, optional, relevant if fullEV is False
+ - nq1: number of first order states, optional, relevant if fullEV is False
+ - fullEV: if True, the entire eigenvectors are returned, otherwise,
+ only the part associated with q and q1 are returned
+ - normQ: 'byMax': normalize by maximum
+ None: do not normalize
+ OUPUTS:
+ - freq_d: damped frequencies [Hz]
+ - zeta : damping ratios [-]
+ - Q : column eigenvectors
+ - freq_0: natural frequencies [Hz]
+ """
+ n,m = A.shape
+
+ if m!=n:
+ raise Exception('Matrix needs to be squared')
+ if nq is None:
+ if nq1 is None:
+ nq1=0
+ nq = int((n-nq1)/2)
+ else:
+ nq1 = n-2*nq
+ if n!=2*nq+nq1 or nq1<0:
+ raise Exception('Number of 1st and second order dofs should match the matrix shape (n= 2*nq + nq1')
+ Q, Lambda = eig(A, sort=False)
+ v = np.diag(Lambda)
+
+ if not fullEV:
+ Q=np.delete(Q, slice(nq,2*nq), axis=0)
+
+ # Selecting eigenvalues with positive imaginary part (frequency)
+ Ipos = np.imag(v)>0
+ Q = Q[:,Ipos]
+ v = v[Ipos]
+
+ # Frequencies and damping based on compled eigenvalues
+ omega_0 = np.abs(v) # natural cylic frequency [rad/s]
+ freq_d = np.imag(v)/(2*np.pi) # damped frequency [Hz]
+ zeta = - np.real(v)/omega_0 # damping ratio
+ freq_0 = omega_0/(2*np.pi) # natural frequency [Hz]
+
+ # Sorting
+ if sort:
+ I = np.argsort(freq_0)
+ freq_d = freq_d[I]
+ freq_0 = freq_0[I]
+ zeta = zeta[I]
+ Q = Q[:,I]
+
+ # Normalize Q
+ if normQ=='byMax':
+ for j in range(Q.shape[1]):
+ q_j = Q[:,j]
+ scale = np.max(np.abs(q_j))
+ Q[:,j]= Q[:,j]/scale
+ return freq_d, zeta, Q, freq_0
+
+
+
+def eigMK(M, K, sort=True, normQ=None, discardIm=False, freq_out=True, massScaling=True):
+ """
+ Eigenvalue analysis of a mechanical system
+ M, K: mass, and stiffness matrices respectively
+
+ Should be equivalent to calling eig(K, M) in Matlab (NOTE: argument swap)
+ except that frequencies are returned instead of "Lambda"
+
+ OUTPUTS:
+ Q, freq_0 if freq_out
+ Q, Lambda otherwise
+ """
+ return eig(K, M, sort=sort, normQ=normQ, discardIm=discardIm, freq_out=freq_out, massScaling=massScaling)
+
+
+def eigMCK(M, C, K, method='full_matrix', sort=True, normQ=None):
+ """
+ Eigenvalue analysis of a mechanical system
+ M, C, K: mass, damping, and stiffness matrices respectively
+
+ NOTE: full_matrix, state_space and state_space_gen should return the same
+ when damping is present
+ """
+ if np.linalg.norm(C)<1e-14:
+ if method.lower() not in ['state_space', 'state_space_gen']:
+ # No damping
+ Q, freq_0 = eigMK(M, K, sort=sort, freq_out=True, normQ=normQ)
+ freq_d = freq_0
+ zeta = freq_0*0
+ return freq_d, zeta, Q, freq_0
+
+
+ n = M.shape[0] # Number of DOFs
+
+ if method.lower()=='diag_beta':
+ ## using K, M and damping assuming diagonal beta matrix (Rayleigh Damping)
+ Q, Lambda = eig(K,M, sort=False) # provide scaled EV, important, no sorting here!
+ freq_0 = np.sqrt(np.diag(Lambda))/(2*np.pi)
+ betaMat = np.dot(Q,C).dot(Q.T)
+ xi = (np.diag(betaMat)*np.pi/(2*np.pi*freq_0))
+ xi[xi>2*np.pi] = np.NAN
+ zeta = xi/(2*np.pi)
+ freq_d = freq_0*np.sqrt(1-zeta**2)
+
+ elif method.lower()=='full_matrix':
+ ## Method 2 - Damping based on K, M and full D matrix
+ Q,v = polyeig(K,C,M, sort=sort, normQ=normQ)
+ #omega0 = np.abs(e)
+ zeta = - np.real(v) / np.abs(v)
+ freq_d = np.imag(v) / (2*np.pi)
+ # Keeping only positive frequencies
+ bValid = freq_d > 1e-08
+ freq_d = freq_d[bValid]
+ zeta = zeta[bValid]
+ Q = Q[:,bValid]
+ # logdec2 = 2*pi*dampratio_sorted./sqrt(1-dampratio_sorted.^2);
+
+ elif method.lower()=='state_space':
+ # See welib.system.statespace.StateMatrix
+ Minv = np.linalg.inv(M)
+ I = np.eye(n)
+ Z = np.zeros((n, n))
+ A = np.block([[np.zeros((n, n)), np.eye(n)],
+ [ -Minv@K , -Minv@C ]])
+ return eigA(A, normQ=normQ, sort=sort)
+
+ elif method.lower()=='state_space_gen':
+ I = np.eye(n)
+ Z = np.zeros((n, n))
+ A = np.block([[Z, I],
+ [-K, -C]])
+ B = np.block([[I, Z],
+ [Z, M]])
+ # solve the generalized eigenvalue problem
+ D, Q = linalg.eig(A, B)
+ # Keeping every other states (assuming pairs..)
+ v = D[::2]
+ Q = Q[:n, ::2]
+
+ # calculate natural frequencies and damping
+ omega_0 = np.abs(v) # natural cyclic frequency [rad/s]
+ freq_d = np.imag(v)/(2*np.pi) # damped frequency [Hz]
+ zeta = - np.real(v)/omega_0 # damping ratio
+
+ else:
+ raise NotImplementedError()
+
+ # Sorting
+ if sort:
+ I = np.argsort(freq_d)
+ freq_d = freq_d[I]
+ zeta = zeta[I]
+ Q = Q[:,I]
+ # Undamped frequency
+ freq_0 = freq_d / np.sqrt(1 - zeta**2)
+ #xi = 2 * np.pi * zeta # pseudo log-dec
+ return freq_d, zeta, Q, freq_0
+
+
+if __name__=='__main__':
+ np.set_printoptions(linewidth=300, precision=4)
+ nDOF = 2
+ M = np.zeros((nDOF,nDOF))
+ K = np.zeros((nDOF,nDOF))
+ C = np.zeros((nDOF,nDOF))
+ M[0,0] = 430000;
+ M[1,1] = 42000000;
+ C[0,0] = 7255;
+ C[1,1] = M[1,1]*0.001;
+ K[0,0] = 2700000.;
+ K[1,1] = 200000000.;
+
+ freq_d, zeta, Q, freq, xi = eigMCK(M,C,K)
+ print(freq_d)
+ print(Q)
+
+
+ #M = diag([3,0,0,0], [0, 1,0,0], [0,0,3,0],[0,0,0, 1])
+ M = np.diag([3,1,3,1])
+ C = np.array([[0.4 , 0 , -0.3 , 0] , [0 , 0 , 0 , 0] , [-0.3 , 0 , 0.5 , -0.2 ] , [ 0 , 0 , -0.2 , 0.2]])
+ K = np.array([[-7 , 2 , 4 , 0] , [2 , -4 , 2 , 0] , [4 , 2 , -9 , 3 ] , [ 0 , 0 , 3 , -3]])
+
+ X,e = polyeig(K,C,M)
+ print('X:\n',X)
+ print('e:\n',e)
+ # Test taht first eigenvector and valur satisfy eigenvalue problem:
+ s = e[0];
+ x = X[:,0];
+ res = (M*s**2 + C*s + K).dot(x) # residuals
+ assert(np.all(np.abs(res)<1e-12))
+
diff --git a/reg_tests/lib/fast_linearization_file.py b/reg_tests/lib/fast_linearization_file.py
new file mode 100644
index 0000000000..3606e6699f
--- /dev/null
+++ b/reg_tests/lib/fast_linearization_file.py
@@ -0,0 +1,391 @@
+"""
+Taken from python-toolbox https://github.com/openfast/python-toolbox
+"""
+import os
+import numpy as np
+import re
+class BrokenFormatError(Exception): pass
+
+class FASTLinearizationFile(dict):
+ """
+ Read/write an OpenFAST linearization file. The object behaves like a dictionary.
+
+ Main keys
+ ---------
+ - 'x', 'xdot' 'u', 'y', 'A', 'B', 'C', 'D'
+
+ Main methods
+ ------------
+ - read, write, toDataFrame, keys, xdescr, ydescr, udescr
+
+ Examples
+ --------
+
+ f = FASTLinearizationFile('5MW.1.lin')
+ print(f.keys())
+ print(f['u']) # input operating point
+ print(f.udescr()) # description of inputs
+
+ # use a dataframe with "named" columns and rows
+ df = f.toDataFrame()
+ print(df['A'].columns)
+ print(df['A'])
+
+ """
+ @staticmethod
+ def defaultExtensions():
+ return ['.lin']
+
+ @staticmethod
+ def formatName():
+ return 'FAST linearization output'
+
+ def __init__(self, filename=None, **kwargs):
+ """ Class constructor. If a `filename` is given, the file is read. """
+ self.filename = filename
+ if filename:
+ self.read(**kwargs)
+
+ def read(self, filename=None, **kwargs):
+ """ Reads the file self.filename, or `filename` if provided """
+
+ # --- Standard tests and exceptions (generic code)
+ if filename:
+ self.filename = filename
+ if not self.filename:
+ raise Exception('No filename provided')
+ if not os.path.isfile(self.filename):
+ raise OSError(2,'File not found:',self.filename)
+ if os.stat(self.filename).st_size == 0:
+ raise EmptyFileError('File is empty:',self.filename)
+ # --- Calling (children) function to read
+ self._read(**kwargs)
+
+ def _read(self, *args, **kwargs):
+ self['header']=[]
+
+ def extractVal(lines, key):
+ for l in lines:
+ if l.find(key)>=0:
+ return l.split(key)[1].split()[0]
+ return None
+
+ def readToMarker(fid, marker, nMax):
+ lines=[]
+ for i, line in enumerate(fid):
+ if i>nMax:
+ raise BrokenFormatError('`{}` not found in file'.format(marker))
+ if line.find(marker)>=0:
+ break
+ lines.append(line.strip())
+ return lines, line
+
+ def readOP(fid, n, name=''):
+ OP=[]
+ Var = {'RotatingFrame': [], 'DerivativeOrder': [], 'Description': []}
+ colNames=fid.readline().strip()
+ dummy= fid.readline().strip()
+ bHasDeriv= colNames.find('Derivative Order')>=0
+ for i, line in enumerate(fid):
+ sp=line.strip().split()
+ if sp[1].find(',')>=0:
+ # Most likely this OP has three values (e.g. orientation angles)
+ # For now we discard the two other values
+ OP.append(float(sp[1][:-1]))
+ iRot=4
+ else:
+ OP.append(float(sp[1]))
+ iRot=2
+ Var['RotatingFrame'].append(sp[iRot])
+ if bHasDeriv:
+ Var['DerivativeOrder'].append(int(sp[iRot+1]))
+ Var['Description'].append(' '.join(sp[iRot+2:]).strip())
+ else:
+ Var['DerivativeOrder'].append(-1)
+ Var['Description'].append(' '.join(sp[iRot+1:]).strip())
+ if i>=n-1:
+ break
+ OP=np.asarray(OP)
+ return OP, Var
+
+ def readMat(fid, n, m, name=''):
+ pattern = re.compile(r"[\*]+")
+ vals=[pattern.sub(' inf ', fid.readline().strip() ).split() for i in np.arange(n)]
+ vals = np.array(vals)
+ try:
+ vals = np.array(vals).astype(float) # This could potentially fail
+ except:
+ raise Exception('Failed to convert into an array of float the matrix `{}`\n\tin linfile: {}'.format(name, self.filename))
+ if vals.shape[0]!=n or vals.shape[1]!=m:
+ shape1 = vals.shape
+ shape2 = (n,m)
+ raise Exception('Shape of matrix `{}` has wrong dimension ({} instead of {})\n\tin linfile: {}'.format(name, shape1, shape2, name, self.filename))
+
+ nNaN = sum(np.isnan(vals.ravel()))
+ nInf = sum(np.isinf(vals.ravel()))
+ if nInf>0:
+ raise Exception('Some ill-formated/infinite values (e.g. `*******`) were found in the matrix `{}`\n\tin linflile: {}'.format(name, self.filename))
+ if nNaN>0:
+ raise Exception('Some NaN values were found in the matrix `{}`\n\tin linfile: `{}`.'.format(name, self.filename))
+ return vals
+
+
+ # Reading
+ with open(self.filename, 'r', errors="surrogateescape") as f:
+ # --- Reader header
+ self['header'], lastLine=readToMarker(f, 'Jacobians included', 30)
+ self['header'].append(lastLine)
+ nx = int(extractVal(self['header'],'Number of continuous states:'))
+ nxd = int(extractVal(self['header'],'Number of discrete states:' ))
+ nz = int(extractVal(self['header'],'Number of constraint states:'))
+ nu = int(extractVal(self['header'],'Number of inputs:' ))
+ ny = int(extractVal(self['header'],'Number of outputs:' ))
+ bJac = extractVal(self['header'],'Jacobians included in this file?')
+ try:
+ self['Azimuth'] = float(extractVal(self['header'],'Azimuth:'))
+ except:
+ self['Azimuth'] = None
+ try:
+ self['RotSpeed'] = float(extractVal(self['header'],'Rotor Speed:')) # rad/s
+ except:
+ self['RotSpeed'] = None
+ try:
+ self['WindSpeed'] = float(extractVal(self['header'],'Wind Speed:'))
+ except:
+ self['WindSpeed'] = None
+
+ for i, line in enumerate(f):
+ line = line.strip()
+ if line.find('Order of continuous states:')>=0:
+ self['x'], self['x_info'] = readOP(f, nx, 'x')
+ elif line.find('Order of continuous state derivatives:')>=0:
+ self['xdot'], self['xdot_info'] = readOP(f, nx, 'xdot')
+ elif line.find('Order of inputs')>=0:
+ self['u'], self['u_info'] = readOP(f, nu, 'u')
+ elif line.find('Order of outputs')>=0:
+ self['y'], self['y_info'] = readOP(f, ny, 'y')
+ elif line.find('A:')>=0:
+ self['A'] = readMat(f, nx, nx, 'A')
+ elif line.find('B:')>=0:
+ self['B'] = readMat(f, nx, nu, 'B')
+ elif line.find('C:')>=0:
+ self['C'] = readMat(f, ny, nx, 'C')
+ elif line.find('D:')>=0:
+ self['D'] = readMat(f, ny, nu, 'D')
+ elif line.find('dUdu:')>=0:
+ self['dUdu'] = readMat(f, nu, nu,'dUdu')
+ elif line.find('dUdy:')>=0:
+ self['dUdy'] = readMat(f, nu, ny,'dUdy')
+ elif line.find('StateRotation:')>=0:
+ pass
+ # TODO
+ #StateRotation:
+ elif line.find('ED M:')>=0:
+ self['EDDOF'] = line[5:].split()
+ self['M'] = readMat(f, 24, 24,'M')
+
+ def toString(self):
+ s=''
+ return s
+
+ def _write(self):
+ with open(self.filename,'w') as f:
+ f.write(self.toString())
+
+ def short_descr(self,slist):
+ def shortname(s):
+ s=s.strip()
+ s = s.replace('(m/s)' , '_[m/s]' );
+ s = s.replace('(kW)' , '_[kW]' );
+ s = s.replace('(deg)' , '_[deg]' );
+ s = s.replace('(N)' , '_[N]' );
+ s = s.replace('(kN-m)' , '_[kNm]' );
+ s = s.replace('(N-m)' , '_[Nm]' );
+ s = s.replace('(kN)' , '_[kN]' );
+ s = s.replace('(rpm)' , '_[rpm]' );
+ s = s.replace('(rad)' , '_[rad]' );
+ s = s.replace('(rad/s)' , '_[rad/s]' );
+ s = s.replace('(rad/s^2)', '_[rad/s^2]' );
+ s = s.replace('(m/s^2)' , '_[m/s^2]');
+ s = s.replace('(deg/s^2)','_[deg/s^2]');
+ s = s.replace('(m)' , '_[m]' );
+ s = s.replace(', m/s/s','_[m/s^2]');
+ s = s.replace(', m/s^2','_[m/s^2]');
+ s = s.replace(', m/s','_[m/s]');
+ s = s.replace(', m','_[m]');
+ s = s.replace(', rad/s/s','_[rad/s^2]');
+ s = s.replace(', rad/s^2','_[rad/s^2]');
+ s = s.replace(', rad/s','_[rad/s]');
+ s = s.replace(', rad','_[rad]');
+ s = s.replace(', -','_[-]');
+ s = s.replace(', Nm/m','_[Nm/m]');
+ s = s.replace(', Nm','_[Nm]');
+ s = s.replace(', N/m','_[N/m]');
+ s = s.replace(', N','_[N]');
+ s = s.replace('(1)','1')
+ s = s.replace('(2)','2')
+ s = s.replace('(3)','3')
+ s= re.sub(r'\([^)]*\)','', s) # remove parenthesis
+ s = s.replace('ED ','');
+ s = s.replace('BD_','BD_B');
+ s = s.replace('IfW ','');
+ s = s.replace('Extended input: ','')
+ s = s.replace('1st tower ','qt1');
+ s = s.replace('2nd tower ','qt2');
+ nd = s.count('First time derivative of ')
+ if nd>=0:
+ s = s.replace('First time derivative of ' ,'');
+ if nd==1:
+ s = 'd_'+s.strip()
+ elif nd==2:
+ s = 'dd_'+s.strip()
+ s = s.replace('Variable speed generator DOF ','psi_rot'); # NOTE: internally in FAST this is the azimuth of the rotor
+ s = s.replace('fore-aft bending mode DOF ' ,'FA' );
+ s = s.replace('side-to-side bending mode DOF','SS' );
+ s = s.replace('bending-mode DOF of blade ' ,'' );
+ s = s.replace(' rotational-flexibility DOF, rad','-ROT' );
+ s = s.replace('rotational displacement in ','rot' );
+ s = s.replace('Drivetrain','DT' );
+ s = s.replace('translational displacement in ','trans' );
+ s = s.replace('finite element node ','N' );
+ s = s.replace('-component position of node ','posN')
+ s = s.replace('-component inflow on tower node','TwrN')
+ s = s.replace('-component inflow on blade 1, node','Bld1N')
+ s = s.replace('-component inflow on blade 2, node','Bld2N')
+ s = s.replace('-component inflow on blade 3, node','Bld3N')
+ s = s.replace('-component inflow velocity at node','N')
+ s = s.replace('X translation displacement, node','TxN')
+ s = s.replace('Y translation displacement, node','TyN')
+ s = s.replace('Z translation displacement, node','TzN')
+ s = s.replace('X translation velocity, node','TVxN')
+ s = s.replace('Y translation velocity, node','TVyN')
+ s = s.replace('Z translation velocity, node','TVzN')
+ s = s.replace('X translation acceleration, node','TAxN')
+ s = s.replace('Y translation acceleration, node','TAyN')
+ s = s.replace('Z translation acceleration, node','TAzN')
+ s = s.replace('X orientation angle, node' ,'RxN')
+ s = s.replace('Y orientation angle, node' ,'RyN')
+ s = s.replace('Z orientation angle, node' ,'RzN')
+ s = s.replace('X rotation velocity, node' ,'RVxN')
+ s = s.replace('Y rotation velocity, node' ,'RVyN')
+ s = s.replace('Z rotation velocity, node' ,'RVzN')
+ s = s.replace('X rotation acceleration, node' ,'RAxN')
+ s = s.replace('Y rotation acceleration, node' ,'RAyN')
+ s = s.replace('Z rotation acceleration, node' ,'RAzN')
+ s = s.replace('X force, node','FxN')
+ s = s.replace('Y force, node','FyN')
+ s = s.replace('Z force, node','FzN')
+ s = s.replace('X moment, node','MxN')
+ s = s.replace('Y moment, node','MyN')
+ s = s.replace('Z moment, node','MzN')
+ s = s.replace('FX', 'Fx')
+ s = s.replace('FY', 'Fy')
+ s = s.replace('FZ', 'Fz')
+ s = s.replace('MX', 'Mx')
+ s = s.replace('MY', 'My')
+ s = s.replace('MZ', 'Mz')
+ s = s.replace('FKX', 'FKx')
+ s = s.replace('FKY', 'FKy')
+ s = s.replace('FKZ', 'FKz')
+ s = s.replace('MKX', 'MKx')
+ s = s.replace('MKY', 'MKy')
+ s = s.replace('MKZ', 'MKz')
+ s = s.replace('Nodes motion','')
+ s = s.replace('cosine','cos' );
+ s = s.replace('sine','sin' );
+ s = s.replace('collective','coll.');
+ s = s.replace('Blade','Bld');
+ s = s.replace('rotZ','TORS-R');
+ s = s.replace('transX','FLAP-D');
+ s = s.replace('transY','EDGE-D');
+ s = s.replace('rotX','EDGE-R');
+ s = s.replace('rotY','FLAP-R');
+ s = s.replace('flapwise','FLAP');
+ s = s.replace('edgewise','EDGE');
+ s = s.replace('horizontal surge translation DOF','Surge');
+ s = s.replace('horizontal sway translation DOF','Sway');
+ s = s.replace('vertical heave translation DOF','Heave');
+ s = s.replace('roll tilt rotation DOF','Roll');
+ s = s.replace('pitch tilt rotation DOF','Pitch');
+ s = s.replace('yaw rotation DOF','Yaw');
+ s = s.replace('vertical power-law shear exponent','alpha')
+ s = s.replace('horizontal wind speed ','WS')
+ s = s.replace('propagation direction','WD')
+ s = s.replace(' pitch command','pitch')
+ s = s.replace('HSS_','HSS')
+ s = s.replace('Bld','B')
+ s = s.replace('tower','Twr')
+ s = s.replace('Tower','Twr')
+ s = s.replace('Nacelle','Nac')
+ s = s.replace('Platform','Ptfm')
+ s = s.replace('SrvD','SvD')
+ s = s.replace('Generator torque','Qgen')
+ s = s.replace('coll. blade-pitch command','PitchColl')
+ s = s.replace('wave elevation at platform ref point','WaveElevRefPoint')
+ s = s.replace('1)','1');
+ s = s.replace('2)','2');
+ s = s.replace('3)','3');
+ s = s.replace(',','');
+ s = s.replace(' ','');
+ s=s.strip()
+ return s
+ return [shortname(s) for s in slist]
+
+ def xdescr(self):
+ if 'x_info' in self.keys():
+ return self.short_descr(self['x_info']['Description'])
+ else:
+ return []
+
+ def xdotdescr(self):
+ if 'xdot_info' in self.keys():
+ return self.short_descr(self['xdot_info']['Description'])
+ else:
+ return []
+
+ def ydescr(self):
+ if 'y_info' in self.keys():
+ return self.short_descr(self['y_info']['Description'])
+ else:
+ return []
+ def udescr(self):
+ if 'u_info' in self.keys():
+ return self.short_descr(self['u_info']['Description'])
+ else:
+ return []
+
+ def toDataFrame(self):
+ import pandas as pd
+ dfs={}
+
+ xdescr_short = self.xdescr()
+ xdotdescr_short = self.xdotdescr()
+ ydescr_short = self.ydescr()
+ udescr_short = self.udescr()
+
+ if 'A' in self.keys():
+ dfs['A'] = pd.DataFrame(data = self['A'], index=xdescr_short, columns=xdescr_short)
+ if 'B' in self.keys():
+ dfs['B'] = pd.DataFrame(data = self['B'], index=xdescr_short, columns=udescr_short)
+ if 'C' in self.keys():
+ dfs['C'] = pd.DataFrame(data = self['C'], index=ydescr_short, columns=xdescr_short)
+ if 'D' in self.keys():
+ dfs['D'] = pd.DataFrame(data = self['D'], index=ydescr_short, columns=udescr_short)
+ if 'x' in self.keys():
+ dfs['x'] = pd.DataFrame(data = np.asarray(self['x']).reshape((1,-1)), columns=xdescr_short)
+ if 'xdot' in self.keys():
+ dfs['xdot'] = pd.DataFrame(data = np.asarray(self['xdot']).reshape((1,-1)), columns=xdotdescr_short)
+ if 'u' in self.keys():
+ dfs['u'] = pd.DataFrame(data = np.asarray(self['u']).reshape((1,-1)), columns=udescr_short)
+ if 'y' in self.keys():
+ dfs['y'] = pd.DataFrame(data = np.asarray(self['y']).reshape((1,-1)), columns=ydescr_short)
+ if 'M' in self.keys():
+ dfs['M'] = pd.DataFrame(data = self['M'], index=self['EDDOF'], columns=self['EDDOF'])
+ if 'dUdu' in self.keys():
+ dfs['dUdu'] = pd.DataFrame(data = self['dUdu'], index=udescr_short, columns=udescr_short)
+ if 'dUdy' in self.keys():
+ dfs['dUdy'] = pd.DataFrame(data = self['dUdy'], index=udescr_short, columns=ydescr_short)
+
+ return dfs
+
+
diff --git a/reg_tests/lib/rtestlib.py b/reg_tests/lib/rtestlib.py
index 59dc4deaac..e90ca95820 100644
--- a/reg_tests/lib/rtestlib.py
+++ b/reg_tests/lib/rtestlib.py
@@ -25,7 +25,9 @@
import shutil
def exitWithError(error, code=1):
- print(error)
+ # Making errors a bit more visible.
+ # The best would be colors. I tried with termcolor.cprint but failed.
+ print('\n\n'+'Error: '+error+'\n\n')
sys.exit(code)
def validInput(argv, nArgsExpected):
diff --git a/reg_tests/r-test b/reg_tests/r-test
index ef6ab57591..091660bef2 160000
--- a/reg_tests/r-test
+++ b/reg_tests/r-test
@@ -1 +1 @@
-Subproject commit ef6ab575919f1db597702f1c3f86a16bdc2b4338
+Subproject commit 091660bef274e3057c9cb32f9a10131f0021b843
diff --git a/vs-build/AeroDyn/AeroDyn_Driver.vfproj b/vs-build/AeroDyn/AeroDyn_Driver.vfproj
index e4b75a5c98..08ce82b7ec 100644
--- a/vs-build/AeroDyn/AeroDyn_Driver.vfproj
+++ b/vs-build/AeroDyn/AeroDyn_Driver.vfproj
@@ -26,7 +26,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
@@ -56,7 +56,7 @@
-
+
@@ -76,7 +76,7 @@
-
+