diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..1c757d6d4e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,26 @@ +# System, cache and editor files +**/__pycache__ +**/.DS_Store + +.editorconfig +.idea +.git +.github +.gitignore +.pytest_cache +.pre-commit-config.yaml +.readthedocs.yml +.coverage +Procfile +README.md + +# Never bake in environment variables +.env +.env* +google_credentials.json +# See: https://github.com/google-github-actions/auth/issues/123 +gha-creds-*.json +gcp-creds-*.json + +.devcontainer/.zsh_history +share/docker diff --git a/.github/workflows/automated-dev-tests.yml b/.github/workflows/automated-dev-tests.yml index 5c1d4a984a..0d6d3f2201 100644 --- a/.github/workflows/automated-dev-tests.yml +++ b/.github/workflows/automated-dev-tests.yml @@ -50,8 +50,7 @@ jobs: products: Simulink - 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev - name: Setup workspace @@ -137,8 +136,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev - name: Setup workspace @@ -187,8 +185,7 @@ jobs: products: Simulink - 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev # gcovr @@ -242,8 +239,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -280,8 +276,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -318,8 +313,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -344,7 +338,7 @@ jobs: ### BUILD AND TEST JOBS build-test-uadriver-debug: - # UA driver requires -DUA_OUTS, cannot be compiled with other + # UA driver used to require -DUA_OUTS runs-on: ubuntu-22.04 steps: - name: Checkout @@ -358,8 +352,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev - name: Setup workspace @@ -379,7 +372,6 @@ jobs: -DVARIABLE_TRACKING=OFF \ -DBUILD_TESTING:BOOL=ON \ -DCTEST_PLOT_ERRORS:BOOL=ON \ - -DCMAKE_Fortran_FLAGS="-DUA_OUTS=ON" \ ${GITHUB_WORKSPACE} - name: Build all working-directory: ${{runner.workspace}}/openfast/build @@ -420,8 +412,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -478,8 +469,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -539,8 +529,7 @@ jobs: 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 + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -587,8 +576,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -721,8 +709,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -771,8 +758,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -821,8 +807,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -871,8 +856,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -921,8 +905,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -971,8 +954,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev @@ -1020,8 +1002,7 @@ jobs: 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" + pip install -r requirements.txt sudo apt-get update -y sudo apt-get install -y libopenblas-dev libopenblas-openmp-dev sudo apt-get install -y libhdf5-dev libnetcdf-dev libopenmpi-dev libyaml-cpp-dev diff --git a/.github/workflows/build-docker-image-automatic.yml b/.github/workflows/build-docker-image-automatic.yml new file mode 100644 index 0000000000..01b80fcac2 --- /dev/null +++ b/.github/workflows/build-docker-image-automatic.yml @@ -0,0 +1,59 @@ +# This workflow builds an OpenFAST docker image for the linux/amd64 and linux/aarch64 architectures on merge into +# `main` from a release candidate branch. The image is tagged both with "latest" and the version extracted from the +# release candidate branch's name (e.g. "rc-3.5.3") before being pushed to the `nrel/openfast` repository. The build +# cache is stored in GitHub actions. +name: build-docker-image-automatic + +on: + release: + types: + - released + +jobs: + build-and-push: + runs-on: ubuntu-latest + timeout-minutes: 300 + env: + DOCKERFILE_PATH: share/docker/Dockerfile + DOCKERHUB_REPOSITORY: nrel/openfast + GH_REGISTRY: ghcr.io/OpenFAST/openfast + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # Commenting out until we get the NREL DockerHub credentials + # - name: Log in to DockerHub + # uses: docker/login-action@v3 + # with: + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.GH_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract tag from release candidate branch name + id: extract-tag + run: echo "openfast-tag=$(expr substr "${{ github.head_ref }}" 4 100)" >> $GITHUB_OUTPUT + + - name: Build and push to registry + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ env.DOCKERFILE_PATH }} + platforms: linux/amd64,linux/aarch64 + tags: | + ${{ env.GH_REGISTRY }}:${{ steps.extract-tag.outputs.openfast-tag }},${{ env.DOCKERHUB_REPOSITORY }}:latest +# ${{ env.DOCKERHUB_REPOSITORY }}:${{ steps.extract-tag.outputs.openfast-tag }},${{ env.DOCKERHUB_REPOSITORY }}:latest + push: true + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/build-docker-image-manual.yml b/.github/workflows/build-docker-image-manual.yml new file mode 100644 index 0000000000..608bd02307 --- /dev/null +++ b/.github/workflows/build-docker-image-manual.yml @@ -0,0 +1,72 @@ +# This manually-triggered workflow builds OpenFAST docker images for the linux/amd64 and linux/aarch64 architectures for +# the specified git ref (this can be a branch, tag, or commit hash). The image is tagged with the given tag and pushed +# to the `nrel/openfast` repository. The build cache is stored in GitHub actions. +name: build-docker-image-manual + +on: + workflow_dispatch: + inputs: + tag: + description: 'Tag for Docker image (excluding the "v" prefix e.g. 3.5.3)' + required: true + ref: + description: 'Branch, tag, or commit SHA to build from' + required: true + default: main + +jobs: + build-and-push: + runs-on: ubuntu-latest + timeout-minutes: 300 + env: + DOCKERFILE_PATH: share/docker/Dockerfile + DOCKERFILE_PERMALINK: https://raw.githubusercontent.com/OpenFAST/openfast/main/share/docker/Dockerfile + DOCKERHUB_REPOSITORY: nrel/openfast + GH_REGISTRY: ghcr.io/OpenFAST/openfast + permissions: + contents: read + packages: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.ref }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # Commenting out until we get the NREL DockerHub credentials + # - name: Log in to DockerHub + # uses: docker/login-action@v3 + # with: + # username: ${{ secrets.DOCKERHUB_USERNAME }} + # password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.GH_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # The updated Dockerfile is only available in the repository at the tag v3.5.3 and above. To build versions of + # OpenFAST that are below this version, the updated Dockerfile from that tag of the repository has to be acquired + # before building. For versions >= v3.5.3, the Dockerfile is already there so this step does nothing. + - name: Get Dockerfile for versions < 3.5.3 + run: | + if [ ! -f ${{ env.DOCKERFILE_PATH }} ]; \ + then wget -O ${{ env.DOCKERFILE_PATH }} ${{ env.DOCKERFILE_PERMALINK }}; \ + fi + + - name: Build and push to registry + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ env.DOCKERFILE_PATH }} + platforms: linux/amd64,linux/aarch64 + tags: | + ${{ env.GH_REGISTRY }}:${{ github.event.inputs.tag }} +# ${{ env.DOCKERHUB_REPOSITORY }}:${{ github.event.inputs.tag }} + push: true + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/test-build-docker-image.yml b/.github/workflows/test-build-docker-image.yml new file mode 100644 index 0000000000..1bd4d7b96b --- /dev/null +++ b/.github/workflows/test-build-docker-image.yml @@ -0,0 +1,38 @@ +# This workflow tests building an OpenFAST docker image for the linux/amd64 architecture on push to a release candidate +# branch. The build cache is stored in GitHub actions. +name: test-build-docker-image + +on: + pull_request: + branches: + - main + +jobs: + test-build: + if: startsWith(github.head_ref, 'rc-') + runs-on: ubuntu-latest + timeout-minutes: 300 + env: + DOCKERFILE_PATH: share/docker/Dockerfile + DOCKERHUB_REPOSITORY: nrel/openfast + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Extract tag from release candidate branch name + id: extract-tag + run: echo "openfast-tag=$(expr substr "${{ github.head_ref }}" 4 100)" >> $GITHUB_OUTPUT + + - name: Test building docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ env.DOCKERFILE_PATH }} + platforms: linux/amd64 + tags: ${{ env.DOCKERHUB_REPOSITORY }}:${{ steps.extract-tag.outputs.openfast-tag }} + push: false + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore index 0b6dd4368e..8004a8eb5d 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,8 @@ vs-build/ .atom .fortls .devcontainer +.idea + # backup files *.asv ~$*.xlsx @@ -54,4 +56,3 @@ vs-build/ #Simulink cache files varcache *.slxc - diff --git a/CMakeLists.txt b/CMakeLists.txt index 3727f6f3de..2989bfe576 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,12 @@ include(${CMAKE_SOURCE_DIR}/cmake/set_rpath.cmake) #------------------------------------------------------------------------------- if (OPENMP OR BUILD_FASTFARM OR BUILD_OPENFAST_CPP_API) - FIND_PACKAGE(OpenMP REQUIRED) + if (OPENMP) + FIND_PACKAGE(OpenMP REQUIRED) + else() + # Optional for FF or the CPP interface + FIND_PACKAGE(OpenMP) + endif() if (OpenMP_Fortran_FOUND) set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${OpenMP_Fortran_FLAGS}") link_libraries("${OpenMP_Fortran_LIBRARIES}") @@ -204,6 +209,7 @@ set(OPENFAST_MODULES icefloe wakedynamics awae + lindyn map turbsim supercontroller diff --git a/docs/OtherSupporting/OutListParameters.xlsx b/docs/OtherSupporting/OutListParameters.xlsx index 6828ce34bf..2ece7d48db 100644 Binary files a/docs/OtherSupporting/OutListParameters.xlsx and b/docs/OtherSupporting/OutListParameters.xlsx differ diff --git a/docs/changelogs/v3.5.3.md b/docs/changelogs/v3.5.3.md new file mode 100644 index 0000000000..1dc519fcee --- /dev/null +++ b/docs/changelogs/v3.5.3.md @@ -0,0 +1,133 @@ +**Feature or improvement description** +Pull request to merge `rc-3.5.3` into `main` and create a tagged release for v3.5.3. + +See the milestone and project pages for additional information + + https://github.com/OpenFAST/openfast/milestone/13 + +Test results, if applicable +See GitHub Actions + +### Release checklist: +- [ ] Update the documentation version in docs/conf.py +- [ ] Update the versions in docs/source/user/api_change.rst +- [ ] Verify readthedocs builds correctly +- [ ] Create a tag in OpenFAST +- [ ] Create a merge commit in r-test and add a corresponding annotated tag +- [ ] Compile executables for Windows builds + - [ ] AeroDyn_Driver_x64.exe + - [ ] AeroDyn_Driver_x64_OpenMP.exe + - [ ] AeroDyn_Inflow_C_Binding_x64.dll + - [ ] AeroDyn_Inflow_C_Binding_x64_OpenMP.dll + - [ ] BeamDyn_Driver_x64.exe + - [ ] DISCON.dll (x64) + - [ ] DISCON_ITIBarge.dll (x64) + - [ ] DISCON_OC3Hywind.dll (x64) + - [ ] DISCON_SC.dll (x64) + - [ ] FAST.Farm_x64.exe + - [ ] FAST.Farm_x64_OMP.exe + - [ ] FAST_SFunc.mexw64 + - [ ] HydroDynDriver_x64.exe + - [ ] HydroDyn_C_Binding_x64.dll + - [ ] IfW_C_Binding_x64.dll + - [ ] InflowWind_Driver_x64.exe + - [ ] InflowWind_Driver_x64_OpenMP.exe + - [ ] MoorDyn_Driver_x64.exe + - [ ] MoorDyn_C_Binding_x64.dll + - [ ] OpenFAST-Simulink_x64.dll + - [ ] openfast_x64.exe + +# Changelog + +## Overview + +This release includes a long awaited set of bug fixes for linearization with BeamDyn. Anyone needing to linearize with BeamDyn should not use any version of OpenFAST prior to this release. + +Other notable improvements include corrections to turbine indexing when coupled to external codes such as AMR-Wind, new linearization regression tests, and new docker images (thanks to first time contributor @cortadocodes at the @Octue organization). + + +## General + +### Build systems + +#2116 VSbuild: always build Registry as release x64 (@andrew-platt) +#2120 #2125 CMake: openmp optional for FF and CPP if not explicitly requested (@andrew-platt and @deslaughter) +#2128 VSbuild: set VS version to VS 2017 (@andrew-platt) +#2138 Remove linking of implicit Fortran libraries. (@jrood-nrel) + + +### Docker builds + +#2124 Update dockerfile and facilitate nrel/openfast Docker Hub registry, with documentation (@cortadocodes, first time contributor) +#2139 Add final dockerfile updates (@cortadocodes) +#2141 GH actions to push docker image to Github container registry (@mayankchetan, first time contributor) + + +### GH actions + +#2041 Upgrade to setup-python@v4 and cache@v4 for GH actions (@andrew-platt) +#2129 Fix cache failure in Github Actions caused by setup-python (@deslaughter) + +### Documentation + +#2130 Fix cache failure in Github Actions caused by setup-python (@andrew-platt) +#2144 Edit to readthedocs.io -- Adding Internal Reference Hyperlink for appendixD.rst (@reilandsberger, first time contributor) +#2145 Docs/update for 3.5.3 release (@andrew-platt) + + +## Solvers + +### OpenFAST + +#2060 Fix BD + AD linearization indexing (negative damping results) (@deslaugher and @andrew-platt) + + +## Module changes + +### Multiple + +#2118 Fix use of uninitialized variables in FAST.Farm and increase stack size in Visual Studio (@deslaughter and @andrew-platt) + + +### BeamDyn + +#2063 Fix bug in BD linearization resulting from reference rotation change (@deslaughter) +#2085 Bug: BeamDyn Initial Strain and Linearization (@deslaughter) + + +### MoorDyn + +#2049 Backport of bathymetry bugfixes in #2013 and #2016 (@RyanDavies19) + + +### OpenFAST library + +#2097 Consistent use of turbine indexing when coupled to c/c++ (@andrew-platt and @deslaughter) + + +### ServoDyn + +#2079 Handling of Paths for SrvD UserSubs Input Files (@rdamiani) +#2134 Bugfix seg fault if blade StC used while writing summary file (@andrew-platt) + + +### TurbSim + +#2102 TurbSim: increase filename to 1024 characters (@andrew-platt) + + +## Regression tests + +#2038 Add linearization regression tests (@andrew-platt) +#2055 Lin tests: increase out precision, error printing full filename, add SD linearization test (@andrew-platt) + + + +## Input file changes + +No input files change with this release, as this only includes minor bugfixes. + +Full list of changes: https://openfast.readthedocs.io/en/main/source/user/api_change.html + +Full input file sets: https://github.com/OpenFAST/r-test/tree/v3.5.3 (example input files from the regression testing) + diff --git a/docs/conf.py b/docs/conf.py index 0f2d012146..c0432bfcaf 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -72,6 +72,7 @@ def runDoxygen(sourcfile, doxyfileIn, doxyfileOut): 'source/user/aerodyn-aeroacoustics/references.bib', 'source/user/aerodyn-olaf/bibliography.bib', 'source/user/aerodyn/bibliography.bib', + 'source/user/elastodyn/bibliography.bib', 'source/user/beamdyn/references.bib', 'source/user/extptfm/bibliography.bib', 'source/user/fast.farm/bibliography.bib', @@ -137,7 +138,7 @@ def runDoxygen(sourcfile, doxyfileIn, doxyfileOut): # The short X.Y version. version = u'3.5' # The full version, including alpha/beta/rc tags. -release = u'v3.5.2' +release = u'v3.5.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/install/index.rst b/docs/source/install/index.rst index 9da66481dc..85c33ac203 100644 --- a/docs/source/install/index.rst +++ b/docs/source/install/index.rst @@ -11,8 +11,8 @@ maintained paths for obtaining an OpenFAST executable. Most users of OpenFAST will not require modifying or compiling the source code. **For the simplest installation of OpenFAST without changing the source -code,** refer to the table in the :ref:`download_binaries` section and read -the corresponding documentation for specific instructions. +code,** refer to the table in the :ref:`download_binaries` or :ref:`use_docker` +sections and read the corresponding documentation for specific instructions. For instructions on compiling, see :ref:`compile_from_source`. .. _download_binaries: @@ -154,6 +154,60 @@ containing the executables, and running a simple test command: cd C:\your\path\Desktop\openfast_binaries\ openfast_x64.exe /h + +.. _use_docker: + +Running OpenFAST with docker +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +OpenFAST is avilable to be run on docker starting with version 3.5.3. Three approaches are shared below. + +Using a docker image from Docker hub +------------------------------------ +Multiple versions of OpenFAST are also available as docker images from our `docker registry `_. +To pull and run one with files from your local machine available, run: + +.. code-block:: shell + + docker run --rm -it --volume=/path/to/files:/files nrel/openfast:latest openfast /files/main.fst + +This command deletes the container (but not the image) when the analysis is finished and leaves the outputs in the same +local directory as the input files. + +You can also run commands interactively inside the container with: + +.. code-block:: shell + + docker run --rm -it --volume=/path/to/files:/files nrel/openfast:latest /bin/bash + +To pull a specific release, substitute the version number in place of `latest` in the above commands (i.e. `nrel/openfast:3.5.3`). + + +Using a docker image from GitHub container registry +--------------------------------------------------- +In addition to images hosted on Docker hub, we also host docker images on our +`GitHub container registry `_. +The commands for pulling an image from the GitHub container repository are +similar to those for pulling and running from Docker hub. + +To pull and run with local files: + +.. code-block:: shell + + docker run --rm -it --volume=/path/to/files:/files ghcr.io/OpenFAST/openfast:latest openfast /files/main.fst + +For running the container interactively: + +.. code-block:: shell + + docker run --rm -it --volume=/path/to/files:/files ghcr.io/OpenFAST/openfast:latest /bin/bash + + +Build your own images +--------------------- +You can also build your own custom images using our `Dockerfile` or base your images on ours. See +`here `_ for more information on this. + + .. _compile_from_source: Compile from source diff --git a/docs/source/testing/regression_test.rst b/docs/source/testing/regression_test.rst index 9262e6bdc1..870fe8143d 100644 --- a/docs/source/testing/regression_test.rst +++ b/docs/source/testing/regression_test.rst @@ -64,12 +64,14 @@ reported as failed. The failure criteria is outlined below. Dependencies ------------ -The following packages are required for regression testing: +The following packages are required for regression testing (see also the +``requirements.txt`` file in the root directory for the python modules): -- Python 3.7+ -- Numpy - CMake and CTest (Optional) -- Bokeh 2.4+ (Optional) +- Python >=3.7,<=3.11 +- numpy +- vtk +- bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3 (Optional) .. _python_driver: diff --git a/docs/source/user/aerodyn-dynamicStall/examples/UA-driver-timeseries.dat b/docs/source/user/aerodyn-dynamicStall/examples/UA-driver-timeseries.dat deleted file mode 100644 index 902354a4db..0000000000 --- a/docs/source/user/aerodyn-dynamicStall/examples/UA-driver-timeseries.dat +++ /dev/null @@ -1,11 +0,0 @@ -Example Time-Series Input File for UnsteadyAero Driver - - -This file has 8 header lines followed by three columns of data: - - -Time Angle of Attack VRel omega -(s) (deg) (m/s) (rad/s) -0.0 0 10 0 -0.01 0 10 0 -0.02 0 10 0 diff --git a/docs/source/user/aerodyn-dynamicStall/examples/UA-driver.dvr b/docs/source/user/aerodyn-dynamicStall/examples/UA-driver.dvr deleted file mode 100644 index 290e7e2245..0000000000 --- a/docs/source/user/aerodyn-dynamicStall/examples/UA-driver.dvr +++ /dev/null @@ -1,28 +0,0 @@ -UnsteadyAero Driver file for Unit NACA. k = 0.077 -------------------------------------------------------------------------------- -FALSE Echo - Echo the input file data (flag) ----------------------- ENVIRONMENTAL CONDITIONS ------------------------------- - 340.29 SpdSound - Speed of sound (m/s) ----------------------- UNSTEADYAERO ------------------------------------------- -"05014051_NACA" OutRootName - The name which prefixes all UnsteadyAero generated files (quoted string) - 40.36 InflowVel - Inflow velocity (m/s) - 1.48 Re - Reynolds number in millions (-) - 3 UAMod - Unsteady Aero Model Switch: 2 - Gonzalez’s variant (changes in Cn,Cc,Cm); 3 - Minnema/Pierce variant (changes in Cc and Cm) -TRUE Flookup – Flag to indicate whether a lookup for f’ will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files -------------------- AIRFOIL PROPERTIES ---------------------------------------- -"05000051_AD15.dat" AirFoil - Airfoil table - 0.55 Chord - Chord length (m) -TRUE UseCm - Use Cm data in airfoil table -------------------- SIMULATION CONTROL ---------------------------------------- - 1 SimMod - Simulation model [ 1 - use reduced frequency model, 2 - use time series data stored in the TimeInputs file and ignore the remaining parameters ] - 3 NCycles - Number of angle-of-attack oscillations (cosine function) over the length of the simulation (-) - 720 StepsPerCycle - Number of timesteps per cycle (-) - 1.8 Frequency - Frequency for the airfoil oscillations (Hz) - 9.685 Amplitude - Amplitude of the oscillations (deg) - 15.195 Mean - Cycle mean (deg) - -180 Phase - Initial phase (num steps) -"UA-driver-timeseries.dat" InputsFile - Time series data in an ASCII input file (whitespace-separated data). 8 header lines, followed by column data. First column is time (sec), second column is angle-of-attack (deg), third column is InflowVel (m/s) -------------------- OUTPUT CONTROL -------------------------------------------- -True SumPrint - Write unsteady aerodynamics summary file (flag) -True WrAFITables - Write the tables of aerodynamic coefficients used internally, with extension ".Coeff.out" (flag) -END of driver input file diff --git a/docs/source/user/aerodyn/bibliography.bib b/docs/source/user/aerodyn/bibliography.bib index dc79859eb4..56ea901810 100644 --- a/docs/source/user/aerodyn/bibliography.bib +++ b/docs/source/user/aerodyn/bibliography.bib @@ -16,6 +16,14 @@ @TECHREPORT{ad-AeroDyn:manualUnsteady note = {NREL/TP-5000-66347} } +@article{ad-UAElast:torquepaper, + title = {Aeroelastic stability of a generalized wind turbine cross-section including unsteady airfoil aerodynamic and dynamic inflow}, + author = {E. Branlard and J.Jonkman and B. Jonkman and M. Singh and E. Mayda and K.Dixon and J H. Porter and G. Vijayakumar}, + year = 2024, + journal = {Jounal of Physics: Conference Series}, +} + + @book{ad-Branlard:book, author = {E. Branlard}, title = {Wind Turbine Aerodynamics and Vorticity-Based Methods: Fundamentals and Recent Applications}, @@ -108,3 +116,10 @@ @article{ad-hammam2022 volume= 1, number=1 } + +@techreport{ad-hammam_NREL:2023, + title={Modeling the Yaw Behavior of Tail Fins for Small Wind Turbines: November 22, 2021-May 21, 2024}, + author={Hammam, Mohamed M and Wood, David and Summerville, Brent}, + year={2023}, + institution={National Renewable Energy Laboratory (NREL), Golden, CO (United States)} +} diff --git a/docs/source/user/aerodyn/input.rst b/docs/source/user/aerodyn/input.rst index 3fe7ff7a38..c5d45a51f6 100644 --- a/docs/source/user/aerodyn/input.rst +++ b/docs/source/user/aerodyn/input.rst @@ -883,22 +883,26 @@ An example of tail fin input file is given below: 0 TFinIndMod - Model for induced velocity calculation {0: none, 1:rotor-average} (switch) ====== Polar-based model ================================ [used only when TFinMod=1] 1 TFinAFID - Index of Tail fin airfoil number [1 to NumAFfiles] - ====== Unsteady slender body model ===================== [used only when TFinMod=2] - [TODO inputs for model 2] + ====== Unsteady slender body model ===================== [used only when TFinMod=2] + 0.9 TFinKp - Tail fin moment of area about reference point + 0.3,0.1,0.1 TFinSigma - Tail fin empirical constant for vortex separation functions + 40,60,60 TFinAStar - Tail fin initial angles for vortex separation functions (deg) + 3.1416 TFinKv - Tail fin vortex lift coefficient + 1.3 TFinCDc - Tail fin drag coefficient General inputs ~~~~~~~~~~~~~~ -**TFinMod** Switch to select a model for the tail fin aerodynamics: +``TFinMod`` is a switch to select a model for the tail fin aerodynamics: 0) none (the aerodynamic forces are zero), 1) polar-based, 2) USB-based (see :numref:`TF-aerotheory`). (switch) -**TFinArea** Area of the tail fin. (m^2) +``TFinArea`` is the area of the tail fin. (m^2) This is the plan form area of the tail fin plate used to relate the local dynamic pressure and airfoil coefficients to aerodynamic loads. This value must not be negative and is only used when TFinMod is set to 1. (m^2) -**TFinRefP_n** Undeflected position (:math:`x_{\text{ref},x_n},x_{\text{ref},y_n}, x_{\text{ref},z_n}`) of the tail fin from the tower top in nacelle coordinates. +``TFinRefP_n`` is the undeflected position (:math:`x_{\text{ref},x_n},x_{\text{ref},y_n}, x_{\text{ref},z_n}`) of the tail fin from the tower top in nacelle coordinates. (formerly defined using ``TFinCPxn``, ``TFinCPyn``, ``TFinCPzn``). The distances defines the configuration for a furl angle of zero. For a typical upwind wind turbine, @@ -908,7 +912,7 @@ For a typical upwind wind turbine, See :numref:`figTFGeom` and :numref:`figTFcoord1`. (m) -**TFinAngles** Angles (:math:`\theta_\text{skew},\theta_\text{tilt}, \theta_\text{bank}`) of the tail fin +``TFinAngles`` are the angles (:math:`\theta_\text{skew},\theta_\text{tilt}, \theta_\text{bank}`) of the tail fin (formerly defined as ``TFinSkew``, ``TFinTilt``, ``TFinBank``). See :numref:`figTFGeom` and :numref:`figTFcoord1`. These angles define the chordline at a furl angle of zero, where the chordline is assumed to be passing through the reference point. @@ -925,7 +929,7 @@ This value must be greater than -180 and less than or equal to 180 degrees. -**TFinIndMod** +``TFinIndMod`` Switch to select a model for the calculation of the velocity induced by the rotor and its wake on the tailfin (not the induced velocity from the tailfin wing). The options available are: 0) none (the induced velocity is zero) @@ -936,7 +940,7 @@ The options available are: Polar-based model inputs ~~~~~~~~~~~~~~~~~~~~~~~~ -**TFinAFID** +``TFinAFID`` This integer tells AeroDyn which of the input airfoil files (``AFNames``) is assigned to the tail fin. For instance, a value of 2 means that the tail fin will use ``AFNames(2)`` for the local tail fin airfoil. This value must be @@ -945,7 +949,21 @@ between 1 and ``NumAFfiles`` and is only used when TFinMod is set to 1. (-) Unsteady slender body (USB) model inputs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Refer to :numref:`TF-aerotheory` and :cite:`ad-hammam_NREL:2023` for guidance on how to select parameters for the unsteady slender body theory based model. -This option is currently not available and will be documented in a future release. +``TFinKp`` +Potential lift coefficient for unsteady aerodynamics. ``TFinKp`` is used to calculate the potential flow contribution to the unsteady aerodynamic force on the tail fin. +``TFinSigma`` +Tail fin empirical constants characterizing the decay of separation functions used in the unsteady aerodynamic model. The separation functions and their dependence on ``TFinSigma`` are described in :numref:`TF-aerotheory`. + +``TFinAStar`` +Tail fin characteristics angles for separation functions used in the unsteady aerodynamic model. The separation functions and their dependence on ``TFinAStar`` are described in :numref:`TF-aerotheory`. + + +``TFinKv`` +Vortex lift coefficient for unsteady aerodynamics. ``TFinKv`` is used to calculate the vortex flow contribution to the unsteady aerodynamic force on the tail fin. + +``TFinCDc`` +Tail fin drag coefficient used for unsteady aerodynamic model. The drag on the tail fin significantly contributes to the normal force at high yaw angles. diff --git a/docs/source/user/aerodyn/theory_tailfin.rst b/docs/source/user/aerodyn/theory_tailfin.rst index 5c5a356a7e..0d18740aca 100644 --- a/docs/source/user/aerodyn/theory_tailfin.rst +++ b/docs/source/user/aerodyn/theory_tailfin.rst @@ -150,8 +150,6 @@ Where :math:`\boldsymbol{V}_{\text{ind},\text{blade}}[i_b, i_r]` is the induced More advanced models could set the induced velocity to zero when outside of the wake boundary, or include a tower-shadow-like wake model. Such option is not yet available. - - Polar-based model ----------------- @@ -163,9 +161,25 @@ The user only needs to indicate the index `TFinAFIndex` within the list `AFNames Unsteady slender body model --------------------------- -The unsteady slender body (USB) model is documented in :cite:`ad-hammam2022`. +The unsteady aerodynamics of the tail fin is modeled based on Unsteady Slender Body Theory. +The theory is extended to include the effect of high yaw angle :cite:`ad-hammam_NREL:2023`. + +The normal force on the tail fin can be described as the sum of three contributions (potential lift, vortex lift, and drag), weighted by separation functions :math:`x_i` as: + +.. math:: :label: TFUSBForce + + N = \frac{\rho}{2} A_{tf} \bigg( K_p x_1 V_{\text{rel},x} V_{\text{rel},y} + \Big[x_2 K_v+(1- x_3)C_{Dc} \Big] V_{\text{rel},y}\big|V_{\text{rel},y}\big|\bigg) + + +where :math:`\rho` is the density of air, :math:`A_{tf}` is the tail fin area, :math:`K_p` is the potential lift coefficient and :math:`K_v` is the vortex lift coefficient, and :math:`C_{Dc}` is the drag coefficient. +:math:`x_i` are the separation functions calculated using a quasi-steady approximation as: + +.. math:: :label: TFUSBxiEquation -The theory will be implemented and documented in a future release. + x_i = (1+exp{[\sigma_i (|\gamma_{tf}|-\alpha^*_i)]})^{-1} +where :math:`\sigma_i` are empirical constants characterizing the decay of separation functions, :math:`\gamma_{tf}` is the yaw angle of the tail fin with respect to the free-stream wind (:math:`V_{\text{wind}}`), :math:`\alpha^*_i` are the characteristics angles for separation functions. +:math:`x_i` takes on a value between 0 and 1, and are used to activate or deactivate a the contribution of potential lift, vortex lift and draft to the normal force on the tail fin. +The normal force is assumed to act at the user defined reference point on the tail fin and the moment of the normal force is calculated accordingly. diff --git a/docs/source/user/aerodyn/theory_ua.rst b/docs/source/user/aerodyn/theory_ua.rst index 005e478fdd..2a67b8fdd5 100644 --- a/docs/source/user/aerodyn/theory_ua.rst +++ b/docs/source/user/aerodyn/theory_ua.rst @@ -25,6 +25,12 @@ speed increases, but stall is delayed. + + + +.. _ua_theory: + + Theory ------ @@ -489,6 +495,12 @@ where :math:`\alpha_{50}` is computed the same way as :math:`\alpha_{34}` (using + + + + +.. _UA_inputs: + Inputs ------ @@ -503,6 +515,10 @@ An example of profile data (containing some of the unsteady aerodynamic paramete :download:`(here) `. +The unsteady aerodynamic driver inputs are documented in :numref:`ua_driver`. + + + .. _UA_AFI_defaults: Calculating Default Airfoil Coefficients @@ -579,17 +595,195 @@ to set preprocessor variable ``UA_OUTS`` and recompile the program (OpenFAST, Ae The outputs are written in output files with extension `*.UA.out`. To activate these outputs with `cmake`, compile using ``-DCMAKE_Fortran_FLAGS="-DUA_OUTS=ON"`` +When using the driver, there is no need to use this preprocessor variable. + +.. _ua_aeroelasttheory: + +Aeroelastic simulation of a 2D section +-------------------------------------- + +Aeroelastic simulations of an isolated 2D section are possible using the driver in order to use the unsteady aerodynamic model in a simplified context. +See :numref:`ua_driver`. +The theory and description for the aeroelastic simulation can be found in +:cite:`ad-UAElast:torquepaper`. + + + + +.. _ua_driver: + Driver ------ -A driver is available to run simulations for a single airfoil, using sinusoidal variation of the angle of attack, -or user defined time series of angle of attack, relative wind speed and pitch rate. + +A driver is available to run simulations for a single airfoil. + +Different kind of simulations are possible: + + - using sinusoidal variation of the angle of attack, + - user defined time series of angle of attack, relative wind speed and pitch rate. + - aero elastic simulations with 3 degrees of freedom for the elastic motion of the section in it's 2D plane (flap, edge and torsion), with possibility to prescribe time series of the wind speed, or prescribe the motion of the section. + +The theory and description for the aeroelastic simulation can be found in :cite:`ad-UAElast:torquepaper`. + + + + + +Compilation +~~~~~~~~~~~ Using `cmake`, the driver is compiled using `make unsteadyaero_driver`, resulting as an executable in the `aerodyn` folder. -An example of driver input file is available here: :download:`here <../aerodyn-dynamicStall/examples/UA-driver.dvr>`. -An example of time series input is available here: :download:`here <../aerodyn-dynamicStall/examples/UA-driver-timeseries.dat>` + +Driver Inputs +~~~~~~~~~~~~~ + +An example of input file for the unsteady aerodynamic driver can be found in the `r-test repository `__. + + +The differente inputs are described below. + + + +**Environmental conditions** + + +``FldDens``: Density of working fluid (kg/m^3) + +``KinVisc``: Kinematic viscosity of working fluid (m^2/s) + +``SpdSound``: Speed of sound of working fluid (m/s) + + +**Unsteady aerodynamics options** + +``UAMod`` : Unsteady Aero Model Switch (switch) {2=B-L Gonzalez, 3=B-L Minnema/Pierce, 4=B-L HGM 4-states, 5=B-L 5 states, 6=Oye, 7=Boeing-Vertol} [used only when AFAeroMod=2] + +``FLookup`` : Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files (flag) [used only when AFAeroMod=2] + + +**Airfoil properties** + +``AirFoil``: Airfoil table (Column 1: Angle of Attack (AoA), column 2: Lift coeff, column 3: Drag coeff). + +``Chord`` : Chord length (m) + +``Vec_AQ`` : Vector from reference point "A" to aerodynamic center (~quarter chord) "Q" in airfoil coordinates and in chord length. If "A" is at mid chord values are likely (0, -0.25) (-) + +``Vec_AT`` : Vector from reference point "A" to three-quarter chord point "T" in airfoil coordinates and in chord length. If "A" is at mid chord values are likely (0, 0.25) (-) + +``UseCm`` : Use Cm (moment coefficient) data in airfoil table {true/false} + + +**Simulation control** + +``SimMod``: Simulation model {1=reduced frequency model, 2=prescribed-aero time series, 3=elastic cross section} + + +**Reduced-frequency simulation** (``SimMod=1``) + +``InflowVel`` : Inflow velocity (m/s) + +``NCycles`` : Number of angle-of-attack oscillations over the length of the simulation (-) + +``StepsPerCycle`` : Number of timesteps per cycle (-) + +``Frequency`` : Frequency for the airfoil oscillations (Hz) + +``Amplitude`` : Amplitude of the angle of attack oscillations (deg) + +``Mean`` : Cycle mean (deg) + +``Phase`` : Initial phase (num steps). + + +**Prescribed aerodynamic simulation inputs** (``SimMod=2``) + +``TMax_PA`` : Total run time (s) + +``DT_PA`` : Recommended module time step (s) + +``AeroTSFile``: Time series data in delimited input file (e.g. csv) with 1 header line, 4 columns: Time (s), angle-of-attack (deg), InflowVel (m/s), Pitch rate (rad/s) + + +**Aeroelastic simulation** (``SimMod=3``) + +The theory for the aeroelastic simulation can be found in :numref:`ua_aeroelasttheory`. + +``TMax`` : Total run time (s) + +``DT`` : Time step (s). + +``ActiveDOF`` : List of Degrees of freedom that are active (true or false) + +``InitPos`` : List of initial positions for the elastic degrees of freedom (m, m and rad) + +``InitVel`` : List of initial velocities for the elastic degrees of freedom (m/s, m/s, and rad/s) + +``GFScalingL1`` : Generalized force scaling factors to convert from section loads to generalized loads (3x3). Three values per line. + +``MassMatrixL1`` : Mass matrix (3x3). Three values per line. + +``DampMatrixL1`` : Damping matrix (3x3). Three values per line. + +``StifMatrixL1`` : Stiffness matrix (3x3). Three values per line. + +``Twist`` : Fixed twist of the section when torsion degree of freedom is zero (deg) + +``InflowMod`` : Model for the inflow velocity. {1: constant velocity, 2: time series} + +``Inflow`` : Inflow velocity in x and y direction [used only when InflowMod=1] + +``InflowTSFile`` : Input file for inflow velocity. Delimited file (e.g. csv) with one header line, three columns: Time (s), Ux (m/s), Uy (m/s). [used only when InflowMod=2] + +``MotionMod`` : Model for the motion of the degrees of freedom {1: dynamic, 2: prescribed} + +``MotionTSFile`` : Input file for prescribed motion. Delimited file (e.g. csv) with one header line, 10 columns: Time (s), x (m), y (m), th (rad), velocities, and accelerations. [used only when InflowMod=2] + + +**Output control** + +``SumPrint`` : Write unsteady aerodynamics summary file (flag) + +``WrAFITables`` : Write back the aerodynamic coefficients used internally (flag) + + +**Example CSV input files** + +The unsteady aerodyn driver now relies on CSV files for it's input time series. +The time column does not need to be at a constant time step, but needs to be monotonously increasing. + +Prescribed aero input (``SimMod=2``): + +.. code: + + Time_[s] , Alpha_[deg] , VRel_[m/s] , omega_[rad/s] + 0.0 , 0 , 10 , 0 + 0.01 , 0 , 10 , 0 + + +Inflow file input (``SimMod=3``, ``InflowMod=2``): + +.. code: + + Time_[s] , Ux_[m/s], Uy_[m/s] + 0.0 , 1 , 10 + 1.0 , 2 , 10 + 5.0 , 2 , 8 + 10.0 , 1 , 12 + + +Motion file input (``SimMod=3``, ``MotionMod=2``) (note in this dummy exmaple velocities and accelerations are not provided, but preferably they should be): + +.. code: + + Time_[s] , x_[m] , y_[m] , th_[rad] , xd_[m/s] , yd_[m/s] , thd_[rad/s] , xdd_[m/s^2] , ydd_[m/s^2] , thdd_[rad/s^2] + 0.0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 + 1.0 , 2 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 + 5.0 , 2 , 2 , 2 , 0 , 0 , 0 , 0 , 0 , 0 + 10.0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 diff --git a/docs/source/user/api_change.rst b/docs/source/user/api_change.rst index e91760a11c..5cf14c37a2 100644 --- a/docs/source/user/api_change.rst +++ b/docs/source/user/api_change.rst @@ -10,7 +10,7 @@ The line number corresponds to the resulting line number after all changes are i Thus, be sure to implement each in order so that subsequent line numbers are correct. -OpenFAST v3.5.2 to OpenFAST dev +OpenFAST v3.5.3 to OpenFAST dev ---------------------------------- The HydroDyn module was split into HydroDyn and SeaState. This results in a @@ -33,6 +33,12 @@ SubDyn 59\* \*Exact line number depends on number of entries in various preceeding tables. +OpenFAST v3.5.2 to OpenFAST v3.5.3 +---------------------------------- + +No input file changes were made. + + OpenFAST v3.5.1 to OpenFAST v3.5.2 ---------------------------------- diff --git a/docs/source/user/elastodyn/bibliography.bib b/docs/source/user/elastodyn/bibliography.bib new file mode 100644 index 0000000000..e6c7d35319 --- /dev/null +++ b/docs/source/user/elastodyn/bibliography.bib @@ -0,0 +1,6 @@ +@techreport{ed-hammam2023, + title={Modeling the Yaw Behavior of Tail Fins for Small Wind Turbines: November 22, 2021-May 21, 2024}, + author={Hammam, Mohamed M and Wood, David and Summerville, Brent}, + year={2023}, + institution={National Renewable Energy Laboratory (NREL), Golden, CO (United States)} +} diff --git a/docs/source/user/elastodyn/figs/YawFrictionModel.jpg b/docs/source/user/elastodyn/figs/YawFrictionModel.jpg new file mode 100644 index 0000000000..aa39021ee7 Binary files /dev/null and b/docs/source/user/elastodyn/figs/YawFrictionModel.jpg differ diff --git a/docs/source/user/elastodyn/index.rst b/docs/source/user/elastodyn/index.rst index c95aecd402..6b65d36e8e 100644 --- a/docs/source/user/elastodyn/index.rst +++ b/docs/source/user/elastodyn/index.rst @@ -58,3 +58,4 @@ equations of FAST v7 and the ElastoDyn module of FAST v8 and OpenFAST. coordsys.rst input.rst theory.rst + zrefs.rst diff --git a/docs/source/user/elastodyn/input.rst b/docs/source/user/elastodyn/input.rst index 97d1651845..a9f2fec2de 100644 --- a/docs/source/user/elastodyn/input.rst +++ b/docs/source/user/elastodyn/input.rst @@ -231,6 +231,17 @@ Rotor-Teeter **TeetHSSp** - Rotor-teeter hard-stop linear-spring constant (N-m/rad) [used only for 2 blades and when TeetMod=1] +Yaw-Friction +~~~~~~~~~~~~ + +**YawFrctMod** - Yaw-friction model {0: none, 1: friction without Fz term at the yaw bearing, 2: friction includes Fz term at yaw bearing, 3: user defined model} + +**M_CSmax** - Maximum Coulomb friction torque (N-m)[mu_s*D_eff when YawFrctMod=1 and Fz*mu_s*D_eff when YawFrctMod=2] + +**M_CD** - Dynamic friction moment at null yaw rate (N-m) [mu_d*D_eff when YawFrctMod=1 and Fz*mu_d*D_eff when YawFrctMod=2] + +**sig_v** - Viscous friction coefficient (N-m/(rad/s)) + Drivetrain ~~~~~~~~~~ diff --git a/docs/source/user/elastodyn/theory.rst b/docs/source/user/elastodyn/theory.rst index f687277333..3474835f05 100644 --- a/docs/source/user/elastodyn/theory.rst +++ b/docs/source/user/elastodyn/theory.rst @@ -159,7 +159,41 @@ The total moment on the given degree of freedom is: +.. _ed_yawfriction_theory: +Yaw-friction +------------ +A yaw-friction model is implemented in ElastoDyn based on a Coulomb-viscous approach. +The yaw-friction moment as a function of yaw rate (:math:`\omega`) is shown below in :numref:`figYawFriction` + +.. _figYawFriction: +.. figure:: figs/YawFrictionModel.jpg + :width: 60% + + Yaw-friction model + +The yaw-friction torque :math:`M_f` can be calcualated as follows. + +if :math:`\omega\neq0`: + +.. math:: + M_f = \mu_d\bar{D}\times\text{min}(0,F_z)\times\text{sign}(\omega) - \sigma_v\times\omega + +if :math:`\omega=0` and :math:`\dot{\omega}\neq 0`: + +.. math:: + M_f = \mu_d\bar{D}\times\text{min}(0,F_z)\times\text{sign}(\dot{\omega}) + +if :math:`\omega=0` and :math:`\dot{\omega}=0`: + +.. math:: + M_f = -\text{min}(\mu_s\bar{D}\times|\text{min}(0,F_z)|,|M_z|)\times\text{sign}(M_z) + + +where :math:`\bar{D}` is the effective yaw-bearing race diameter, :math:`\mu_d` is the dynamic friction coefficient, :math:`\mu_s` is the static friction coefficient, :math:`F_z` is effective axial load on yaw-bearing, :math:`M-z` is the external torque on yaw-bearing. +The static 'stiction' (where the static contribution exceeds the dynamic Coulomb friction) is only applied if both the yaw rotational velocity and acceleration at the current time-step are zero. +The static portion of the friction is omitted if the rotational acceleration is not null, (sign(0) is taken as 1). +This is to account for the fact that a 'warm' joint may not feel stiction when crossing through zero velocity in a dynamic sense :cite:`ed-hammam2023` .. _ed_dev_notes: diff --git a/docs/source/user/elastodyn/zrefs.rst b/docs/source/user/elastodyn/zrefs.rst new file mode 100644 index 0000000000..afb6844d57 --- /dev/null +++ b/docs/source/user/elastodyn/zrefs.rst @@ -0,0 +1,9 @@ +.. only:: html + + References + ---------- + +.. bibliography:: bibliography.bib + :labelprefix: ed- + + diff --git a/docs/source/user/subdyn/appendixD.rst b/docs/source/user/subdyn/appendixD.rst index e2bcbab592..3cf6bcef2c 100644 --- a/docs/source/user/subdyn/appendixD.rst +++ b/docs/source/user/subdyn/appendixD.rst @@ -7,7 +7,7 @@ This is a list of all possible output parameters for the SubDyn module. The names are grouped by meaning, but can be ordered in the OUTPUT CHANNELS section of the SubDyn input file as the user sees fit. :math:`M \alpha N \beta`, refers to node :math:`\beta` of member :math:`\alpha`, where :math:`\alpha` is a number in the range [1,9] and -corresponds to row :math:`\alpha` in the MEMBER OUTPUT LIST table (see Section ) and +corresponds to row :math:`\alpha` in the MEMBER OUTPUT LIST table (see :numref:`SD_Member_Output`) and :math:`\beta` is a number in the range [1,9] and corresponds to node :math:`\beta` in the **NodeCnt** list of that table entry. diff --git a/glue-codes/fast-farm/src/FASTWrapper.f90 b/glue-codes/fast-farm/src/FASTWrapper.f90 index e7a4cd176d..6bf777fcae 100644 --- a/glue-codes/fast-farm/src/FASTWrapper.f90 +++ b/glue-codes/fast-farm/src/FASTWrapper.f90 @@ -139,7 +139,7 @@ SUBROUTINE FWrap_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, Init end if !.... multi-turbine options .... - ExternInitData%TurbineID = InitInp%TurbNum + ExternInitData%TurbIDforName = InitInp%TurbNum ExternInitData%TurbinePos = InitInp%p_ref_Turbine ExternInitData%WaveFieldMod = InitInp%WaveFieldMod diff --git a/glue-codes/simulink/CMakeLists.txt b/glue-codes/simulink/CMakeLists.txt index b2b495ec40..736d4553b0 100644 --- a/glue-codes/simulink/CMakeLists.txt +++ b/glue-codes/simulink/CMakeLists.txt @@ -19,6 +19,7 @@ set(MEX_LIBS $ $ + $ $ $ $ diff --git a/modules/aerodyn/CMakeLists.txt b/modules/aerodyn/CMakeLists.txt index 7d5f9e4f03..859dd1e155 100644 --- a/modules/aerodyn/CMakeLists.txt +++ b/modules/aerodyn/CMakeLists.txt @@ -26,6 +26,18 @@ if (GENERATE_TYPES) generate_f90_types(src/FVW_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/FVW_Types.f90) endif() +# BasicAero Library +add_library(basicaerolib STATIC + # UnsteadyAero lib + src/UnsteadyAero.f90 + src/UnsteadyAero_Types.f90 + + # AirFoil Info lib + src/AirfoilInfo.f90 + src/AirfoilInfo_Types.f90 +) +target_link_libraries(basicaerolib ifwlib nwtclibs) + # AeroDyn Library add_library(aerodynlib STATIC src/AeroDyn.f90 @@ -46,14 +58,6 @@ add_library(aerodynlib STATIC src/AeroAcoustics_IO.f90 src/AeroAcoustics_Types.f90 - # UnsteadyAero lib - src/UnsteadyAero.f90 - src/UnsteadyAero_Types.f90 - - # AirFoil Info lib - src/AirfoilInfo.f90 - src/AirfoilInfo_Types.f90 - # FVW lib src/FVW.f90 src/FVW_IO.f90 @@ -63,19 +67,22 @@ add_library(aerodynlib STATIC src/FVW_BiotSavart.f90 src/FVW_Tests.f90 src/FVW_Types.f90 +) +target_link_libraries(aerodynlib basicaerolib nwtclibs) - # ADI lib +# ADI lib +add_library(adilib STATIC src/AeroDyn_Inflow.f90 src/AeroDyn_Inflow_Types.f90 ) -target_link_libraries(aerodynlib ifwlib nwtclibs) +target_link_libraries(adilib aerodynlib ifwlib) # AeroDyn Driver Subs Library add_library(aerodyn_driver_subs STATIC src/AeroDyn_Driver_Subs.f90 src/AeroDyn_Driver_Types.f90 ) -target_link_libraries(aerodyn_driver_subs aerodynlib versioninfolib) +target_link_libraries(aerodyn_driver_subs adilib aerodynlib versioninfolib) # AeroDyn Driver add_executable(aerodyn_driver @@ -88,18 +95,18 @@ add_executable(unsteadyaero_driver src/UnsteadyAero_Driver.f90 src/UA_Dvr_Subs.f90 ) -target_link_libraries(unsteadyaero_driver aerodyn_driver_subs) +target_link_libraries(unsteadyaero_driver basicaerolib lindynlib versioninfolib) # AeroDyn-InflowWind c-bindings interface library add_library(aerodyn_inflow_c_binding SHARED src/AeroDyn_Inflow_C_Binding.f90 ) -target_link_libraries(aerodyn_inflow_c_binding aerodyn_driver_subs versioninfolib) +target_link_libraries(aerodyn_inflow_c_binding adilib aerodyn_driver_subs versioninfolib) if(APPLE OR UNIX) target_compile_definitions(aerodyn_inflow_c_binding PRIVATE IMPLICIT_DLLEXPORT) endif() -install(TARGETS aerodynlib aerodyn_driver_subs aerodyn_driver unsteadyaero_driver aerodyn_inflow_c_binding +install(TARGETS aerodynlib basicaerolib aerodyn_driver_subs aerodyn_driver unsteadyaero_driver aerodyn_inflow_c_binding adilib EXPORT "${CMAKE_PROJECT_NAME}Libraries" RUNTIME DESTINATION bin LIBRARY DESTINATION lib diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index a7cca28d9d..81669a3056 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -389,6 +389,11 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut p%rotors(iR)%TFin%TFinArea = InputFileData%rotors(iR)%TFin%TFinArea p%rotors(iR)%TFin%TFinIndMod = InputFileData%rotors(iR)%TFin%TFinIndMod p%rotors(iR)%TFin%TFinAFID = InputFileData%rotors(iR)%TFin%TFinAFID + p%rotors(iR)%TFin%TFinKp = InputFileData%rotors(iR)%TFin%TFinKp + p%rotors(iR)%TFin%TFinSigma = InputFileData%rotors(iR)%TFin%TFinSigma + p%rotors(iR)%TFin%TFinAStar = InputFileData%rotors(iR)%TFin%TFinAStar + p%rotors(iR)%TFin%TFinKv = InputFileData%rotors(iR)%TFin%TFinKv + p%rotors(iR)%TFin%TFinCDc = InputFileData%rotors(iR)%TFin%TFinCDc enddo @@ -2961,7 +2966,7 @@ subroutine SetInputsForBEMT(p, u, m, indx, errStat, errMsg) !.......................... do k=1,p%NumBlades do j=1,p%NumBlNds - ! Velocity in "p" or "w" system (depending) on AeroProjMod + ! Velocity in "l" or "w" system (depending) on AeroProjMod tmp = m%DisturbedInflow(:,j,k) - u%BladeMotion(k)%TranslationVel(:,j) ! rel_V(j)_Blade(k) m%BEMT_u(indx)%Vx(j,k) = dot_product( tmp, m%orientationAnnulus(1,:,j,k) ) ! normal component (normal to the plane, not chord) of the inflow velocity of the jth node in the kth blade m%BEMT_u(indx)%Vy(j,k) = dot_product( tmp, m%orientationAnnulus(2,:,j,k) ) !+ TwoNorm(m%DisturbedInflow(:,j,k))*(sin()*sin(tilt)*)! tangential component (tangential to the plane, not chord) of the inflow velocity of the jth node in the kth blade @@ -2980,6 +2985,7 @@ subroutine SetInputsForBEMT(p, u, m, indx, errStat, errMsg) do k=1,p%NumBlades do j=1,p%NumBlNds ! inputs for CUA (and CDBEMT): + ! TODO Here we should take the rotation in the airfoil coordinate system instead of the "l" or "w" system m%BEMT_u(indx)%omega_z(j,k) = dot_product( u%BladeMotion(k)%RotationVel( :,j), m%orientationAnnulus(3,:,j,k) ) ! rotation of no-sweep-pitch coordinate system around z of the jth node in the kth blade end do !j=nodes @@ -4505,9 +4511,12 @@ SUBROUTINE TFin_CalcOutput(p, p_AD, u, m, y, ErrStat, ErrMsg ) real(ReKi) :: V_wnd(3) ! wind velocity real(ReKi) :: V_ind(3) ! induced velocity real(ReKi) :: V_str(3) ! structural velocity + real(ReKi) :: V_wnd_tf(3) ! wind velocity real(ReKi) :: force_tf(3) ! force in tf system real(ReKi) :: moment_tf(3) ! moment in tf system real(ReKi) :: alpha, Re, Cx, Cy, q ! Cl, Cd, Cm, + real(ReKi) :: x1, x2, x3,gamma_tf! scaling functions, gamma for unsteady modeling + type(AFI_OutputType) :: AFI_interp ! Resulting values from lookup table integer(intKi) :: ErrStat2 character(ErrMsgLen) :: ErrMsg2 @@ -4523,24 +4532,33 @@ SUBROUTINE TFin_CalcOutput(p, p_AD, u, m, y, ErrStat, ErrMsg ) if (p%TFin%TFinIndMod==TFinIndMod_none) then V_ind = 0.0_ReKi + elseif(p%TFin%TFinIndMod==TFinIndMod_rotavg) then ! TODO TODO print*,'TODO TailFin: compute rotor average induced velocity' V_ind = 0.0_ReKi + else - STOP ! Will never happen + call setErrStat(ErrID_Fatal, 'TailFin model unsupported', ErrStat, ErrMsg, 'TFin_CalcOutput') + endif - V_rel = V_wnd - V_str + V_ind + + V_rel = V_wnd - V_str + V_ind ! relative wind on tail fin V_rel_tf = matmul(u%TFinMotion%Orientation(:,:,1), V_rel) ! from inertial to tf system - alpha = atan2( V_rel_tf(2), V_rel_tf(1)) ! angle of attack + alpha = atan2(V_rel_tf(2), V_rel_tf(1)) ! angle of attack + v_wnd_tf = matmul(u%TFinMotion%Orientation(:,:,1), V_wnd) ! only used for calculation of x1,x2,x3 + gamma_tf = atan2(v_wnd_tf(2), v_wnd_tf(1)) ! only used for calculation of x1,x2,x3 V_rel_orth2 = V_rel_tf(1)**2 + V_rel_tf(2)**2 ! square norm of Vrel in tf system + ! Initialize the tail fin forces to zero + force_tf(:) = 0.0_ReKi + moment_tf(:) = 0.0_ReKi + if (p%TFin%TFinMod==TFinAero_none) then - y%TFinLoad%Force(1:3,1) = 0.0_ReKi - y%TFinLoad%Moment(1:3,1) = 0.0_ReKi + ! Do nothing elseif (p%TFin%TFinMod==TFinAero_polar) then - ! Airfoil coefficients + ! Airfoil coefficients based model Re = sqrt(V_rel_orth2) * p%TFin%TFinChord/p%KinVisc call AFI_ComputeAirfoilCoefs( alpha, Re, 0.0_ReKi, p_AD%AFI(p%TFin%TFinAFID), AFI_interp, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -4548,21 +4566,28 @@ SUBROUTINE TFin_CalcOutput(p, p_AD, u, m, y, ErrStat, ErrMsg ) Cy = AFI_interp%Cl * cos(alpha) + AFI_interp%Cd * sin(alpha) ! Forces in tailfin system q = 0.5 * p%airDens * V_rel_orth2 * p%TFin%TFinArea - force_tf(:) = 0.0_ReKi - moment_tf(:) = 0.0_ReKi + force_tf(1) = Cx * q 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 - ! Transfer to global - y%TFinLoad%Force(1:3,1) = matmul(transpose(u%TFinMotion%Orientation(:,:,1)), force_tf) - y%TFinLoad%Moment(1:3,1) = matmul(transpose(u%TFinMotion%Orientation(:,:,1)), moment_tf) elseif (p%TFin%TFinMod==TFinAero_USB) then - call SetErrStat(ErrID_Fatal, 'Tail fin USB model not yet available', ErrStat, ErrMsg, RoutineName ) - return + ! Unsteady aerodynamic model + + ! Calculate separation function (quasi-steady) + x1 = 1.0_Reki/(1.0_Reki+exp(p%TFin%TFinSigma(1)*((ABS(gamma_tf)*180.0_ReKi/pi)-p%TFin%TFinAStar(1)))) + x2 = 1.0_Reki/(1.0_Reki+exp(p%TFin%TFinSigma(2)*((ABS(gamma_tf)*180.0_ReKi/pi)-p%TFin%TFinAStar(2)))) + x3 = 1.0_Reki/(1.0_Reki+exp(p%TFin%TFinSigma(3)*((ABS(gamma_tf)*180.0_ReKi/pi)-p%TFin%TFinAStar(3)))) + + ! Calculate unsteady force on tail fin + force_tf(2) = 0.5_ReKi * p%AirDens * p%TFin%TFinArea * & + (p%TFin%TFinKp * x1 * V_rel_tf(1) * V_rel_tf(2) + & + (x2 * p%TFin%TFinKv + (1-x3)*p%TFin%TFinCDc) * V_rel_tf(2) * ABS(V_rel_tf(2))) endif + + ! Transfer to global + y%TFinLoad%Force(1:3,1) = matmul(transpose(u%TFinMotion%Orientation(:,:,1)), force_tf) + y%TFinLoad%Moment(1:3,1) = matmul(transpose(u%TFinMotion%Orientation(:,:,1)), moment_tf) ! --- Store m%TFinAlpha = alpha @@ -4576,6 +4601,7 @@ SUBROUTINE TFin_CalcOutput(p, p_AD, u, m, y, ErrStat, ErrMsg ) m%TFinM_i = y%TFinLoad%Moment(1:3,1) END SUBROUTINE TFin_CalcOutput + !---------------------------------------------------------------------------------------------------------------------------------- !> This subroutine calculates the tower loads for the AeroDyn TowerLoad output mesh. SUBROUTINE ADTwr_CalcOutput(p, u, m, y, ErrStat, ErrMsg ) diff --git a/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 b/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 index b17cf094f6..2bc7877acf 100644 --- a/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_AllBldNdOuts_IO.f90 @@ -301,7 +301,7 @@ SUBROUTINE Calc_WriteAllBldNdOutput( p, p_AD, u, m, m_AD, x, y, OtherState, Indx 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 + if (p_AD%WakeMod == WakeMod_FVW) W2B => p_AD%FVW%Bld2Wings(iRot, :) ! From Wing index to blade index ! Initialize some things ErrMsg = '' diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 index 40d4b71039..39f451791b 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -1689,120 +1689,6 @@ subroutine Dvr_WriteOutputs(nt, t, dvr, out, yADI, errStat, errMsg) endif enddo end subroutine Dvr_WriteOutputs - -!---------------------------------------------------------------------------------------------------------------------------------- -!> Read a delimited file with one line of header -subroutine ReadDelimFile(Filename, nCol, Array, errStat, errMsg, nHeaderLines, priPath) - character(len=*), intent(in) :: Filename - integer, intent(in) :: nCol - real(ReKi), dimension(:,:), allocatable, intent(out) :: Array - integer(IntKi) , intent(out) :: errStat ! Status of error message - character(*) , intent(out) :: errMsg ! Error message if errStat /= ErrID_None - integer(IntKi), optional, intent(in ) :: nHeaderLines - character(*) , optional, intent(in ) :: priPath ! Primary path, to use if filename is not absolute - integer :: UnIn, i, j, nLine, nHead - character(len= 2048) :: line - integer(IntKi) :: errStat2 ! local status of error message - character(ErrMsgLen) :: errMsg2 ! temporary Error message - character(len=2048) :: Filename_Loc ! filename local to this function - errStat = ErrID_None - errMsg = "" - - Filename_Loc = Filename - if (present(priPath)) then - if (PathIsRelative(Filename_Loc)) Filename_Loc = trim(PriPath)//trim(Filename) - endif - - ! Open file - call GetNewUnit(UnIn) - call OpenFInpFile(UnIn, Filename_Loc, errStat2, errMsg2); if(Failed()) return - ! Count number of lines - nLine = line_count(UnIn) - allocate(Array(nLine-1, nCol), stat=errStat2); errMsg2='allocation failed'; if(Failed())return - ! Read header - nHead=1 - if (present(nHeaderLines)) nHead = nHeaderLines - do i=1,nHead - read(UnIn, *, IOSTAT=errStat2) line - errMsg2 = ' Error reading line '//trim(Num2LStr(1))//' of file: '//trim(Filename_Loc) - if(Failed()) return - enddo - ! Read data - do I = 1,nLine-1 - read (UnIn,*,IOSTAT=errStat2) (Array(I,J), J=1,nCol) - errMsg2 = ' Error reading line '//trim(Num2LStr(I+1))//' of file: '//trim(Filename_Loc) - if(Failed()) return - end do - close(UnIn) -contains - logical function Failed() - CALL SetErrStat(errStat2, errMsg2, errStat, errMsg, 'ReadDelimFile' ) - Failed = errStat >= AbortErrLev - if (Failed) then - if ((UnIn)>0) close(UnIn) - endif - end function Failed -end subroutine ReadDelimFile - -!---------------------------------------------------------------------------------------------------------------------------------- -!> Counts number of lines in a file -integer function line_count(iunit) - integer, intent(in) :: iunit - character(len=2048) :: line - ! safety for infinite loop.. - integer :: i - integer, parameter :: nline_max=100000000 ! 100 M - line_count=0 - do i=1,nline_max - line='' - read(iunit,'(A)',END=100)line - line_count=line_count+1 - enddo - if (line_count==nline_max) then - print*,'Error: maximum number of line exceeded for line_count' - STOP - endif -100 if(len(trim(line))>0) then - line_count=line_count+1 - endif - rewind(iunit) - return -end function - -!---------------------------------------------------------------------------------------------------------------------------------- -!> Perform linear interpolation of an array, where first column is assumed to be ascending time values -!! First value is used for times before, and last value is used for time beyond -subroutine interpTimeValue(array, time, iLast, values) - real(ReKi), dimension(:,:), intent(in) :: array !< vector of time steps - real(DbKi), intent(in) :: time !< time - integer, intent(inout) :: iLast - real(ReKi), dimension(:), intent(out) :: values !< vector of values at given time - integer :: i - real(ReKi) :: alpha - if (array(iLast,1)> time) then - values = array(iLast,2:) - elseif (iLast == size(array,1)) then - values = array(iLast,2:) - else - ! Look for index - do i=iLast,size(array,1) - if (array(i,1)<=time) then - iLast=i - else - exit - endif - enddo - if (iLast==size(array,1)) then - values = array(iLast,2:) - else - ! Linear interpolation - alpha = (array(iLast+1,1)-time)/(array(iLast+1,1)-array(iLast,1)) - values = array(iLast,2:)*alpha + array(iLast+1,2:)*(1-alpha) - !print*,'time', array(iLast,1), '<=', time,'<', array(iLast+1,1), 'fact', alpha - endif - endif -end subroutine interpTimeValue - !---------------------------------------------------------------------------------------------------------------------------------- !> This subroutine sets up the information needed for plotting VTK surfaces. subroutine setVTKParameters(p_FAST, dvr, ADI, errStat, errMsg, dirname) diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index f92d717b8c..0674d11787 100644 --- a/modules/aerodyn/src/AeroDyn_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_IO.f90 @@ -1266,15 +1266,20 @@ SUBROUTINE ReadTailFinInputs(FileName, TFData, UnEc, ErrStat, ErrMsg) call ParseVar(FileInfo_In, iLine, 'TFinAFID' , TFData%TFinAFID , ErrStat2, ErrMsg2, UnEc); if (Failed()) return; !====== Unsteady slender body model ===================== [used only when TFinMod=2] call ParseCom(FileInfo_in, iLine, DummyLine , ErrStat2, ErrMsg2, UnEc); if (Failed()) return; + call ParseVar(FileInfo_In, iLine, 'TFinKp' , TFData%TFinKp , ErrStat2, ErrMsg2, UnEc); if (Failed()) return; + call ParseAry(FileInfo_In, iLine, 'TFinSigma' , TFData%TFinSigma, 3 , ErrStat2, ErrMsg2, UnEc); if (Failed()) return; + call ParseAry(FileInfo_In, iLine, 'TFinAStar', TFData%TFinAStar, 3 , ErrStat2, ErrMsg2, UnEc); if (Failed()) return; + call ParseVar(FileInfo_In, iLine, 'TFinKv' , TFData%TFinKv , ErrStat2, ErrMsg2, UnEc); if (Failed()) return; + call ParseVar(FileInfo_In, iLine, 'TFinCDc' , TFData%TFinCDc , ErrStat2, ErrMsg2, UnEc); if (Failed()) return; + ! TODO ! --- Triggers TFData%TFinAngles = TFData%TFinAngles*D2R ! deg2rad ! --- Validation on the fly - !if (all((/TFinAero_none,TFinAero_polar, TFinAero_USB/) /= TFData%TFinMod)) then - if (all((/TFinAero_none,TFinAero_polar/) /= TFData%TFinMod)) then - call Fatal('TFinMod needs to be 0, or 1') + if (all((/TFinAero_none,TFinAero_polar,TFinAero_USB/) /= TFData%TFinMod)) then + call Fatal('TFinMod needs to be 0, 1 or 2') endif !if (all((/TFinIndMod_none,TFinIndMod_rotavg/) /= TFData%TFinIndMod)) then if (all((/TFinIndMod_none/) /= TFData%TFinIndMod)) then diff --git a/modules/aerodyn/src/AeroDyn_Registry.txt b/modules/aerodyn/src/AeroDyn_Registry.txt index 8a615e8b4e..6cfb51abd6 100644 --- a/modules/aerodyn/src/AeroDyn_Registry.txt +++ b/modules/aerodyn/src/AeroDyn_Registry.txt @@ -55,6 +55,11 @@ typedef ^ TFinParameterType ReKi TFinChord - - - "Tail fin chord [u typedef ^ TFinParameterType ReKi TFinArea - - - "Tail fin planform area [used only when TFinMod=1]" m^2 typedef ^ TFinParameterType IntKi TFinIndMod - - - "Model for induced velocity calculation {0=none, 1=rotor-average}" (switch) typedef ^ TFinParameterType IntKi TFinAFID - - - "Index of Tail fin airfoil number [1 to NumAFfiles]" - +typedef ^ TFinParameterType ReKi TFinKp - - - "Tail fin potential lift coefficient for unsteady aerodynamics [used only when TFMod=2]" - +typedef ^ TFinParameterType ReKi TFinSigma 3 - - "Tail fin empirical constants characterizing the decay of separation functions [used only when TFMod=2]" - +typedef ^ TFinParameterType ReKi TFinAStar 3 - - "Tail fin characteristics angles for separation functions [used only when TFMod=2]" deg +typedef ^ TFinParameterType ReKi TFinKv - - - "Tail fin vortex lift coefficient for unsteady aerodynamics [used only when TFMod=2]" - +typedef ^ TFinParameterType ReKi TFinCDc - - - "Tail fin drag coefficient for unsteady aerodynamics [used only when TFMod=2]" - # Tail Fin input file typedef ^ TFinInputFileType IntKi TFinMod - - 0 "Tail fin aerodynamics model {0=none, 1=polar-based, 2=USB-based}" (switch) @@ -64,6 +69,11 @@ typedef ^ TFinInputFileType ReKi TFinRefP_n 3 - - "Undeflected posit typedef ^ TFinInputFileType ReKi TFinAngles 3 - - "Tail fin chordline skew, tilt, and bank angles about the reference point" (deg) typedef ^ TFinInputFileType IntKi TFinIndMod - - - "Model for induced velocity calculation {0=none, 1=rotor-average}" (switch) typedef ^ TFinInputFileType IntKi TFinAFID - - - "Index of Tail fin airfoil number [1 to NumAFfiles]" - +typedef ^ TFinInputFileType ReKi TFinKp - - - "Tail fin potential lift coefficient for unsteady aerodynamics [used only when TFMod=2]" - +typedef ^ TFinInputFileType ReKi TFinSigma 3 - - "Tail fin empirical constants characterizing the decay of separation functions [used only when TFMod=2]" - +typedef ^ TFinInputFileType ReKi TFinAStar 3 - - "Tail fin characteristics angles for separation functions [used only when TFMod=2]" deg +typedef ^ TFinInputFileType ReKi TFinKv - - - "Tail fin vortex lift coefficient for unsteady aerodynamics [used only when TFMod=2]" - +typedef ^ TFinInputFileType ReKi TFinCDc - - - "Tail fin drag coefficient for unsteady aerodynamics [used only when TFMod=2]" - diff --git a/modules/aerodyn/src/AeroDyn_Types.f90 b/modules/aerodyn/src/AeroDyn_Types.f90 index f8ab54496e..0d135968a4 100644 --- a/modules/aerodyn/src/AeroDyn_Types.f90 +++ b/modules/aerodyn/src/AeroDyn_Types.f90 @@ -67,6 +67,11 @@ MODULE AeroDyn_Types REAL(ReKi) :: TFinArea = 0.0_ReKi !< Tail fin planform area [used only when TFinMod=1] [m^2] INTEGER(IntKi) :: TFinIndMod = 0_IntKi !< Model for induced velocity calculation {0=none, 1=rotor-average} [(switch)] INTEGER(IntKi) :: TFinAFID = 0_IntKi !< Index of Tail fin airfoil number [1 to NumAFfiles] [-] + REAL(ReKi) :: TFinKp = 0.0_ReKi !< Tail fin potential lift coefficient for unsteady aerodynamics [used only when TFMod=2] [-] + REAL(ReKi) , DIMENSION(1:3) :: TFinSigma = 0.0_ReKi !< Tail fin empirical constants characterizing the decay of separation functions [used only when TFMod=2] [-] + REAL(ReKi) , DIMENSION(1:3) :: TFinAStar = 0.0_ReKi !< Tail fin characteristics angles for separation functions [used only when TFMod=2] [deg] + REAL(ReKi) :: TFinKv = 0.0_ReKi !< Tail fin vortex lift coefficient for unsteady aerodynamics [used only when TFMod=2] [-] + REAL(ReKi) :: TFinCDc = 0.0_ReKi !< Tail fin drag coefficient for unsteady aerodynamics [used only when TFMod=2] [-] END TYPE TFinParameterType ! ======================= ! ========= TFinInputFileType ======= @@ -78,6 +83,11 @@ MODULE AeroDyn_Types REAL(ReKi) , DIMENSION(1:3) :: TFinAngles = 0.0_ReKi !< Tail fin chordline skew, tilt, and bank angles about the reference point [(deg)] INTEGER(IntKi) :: TFinIndMod = 0_IntKi !< Model for induced velocity calculation {0=none, 1=rotor-average} [(switch)] INTEGER(IntKi) :: TFinAFID = 0_IntKi !< Index of Tail fin airfoil number [1 to NumAFfiles] [-] + REAL(ReKi) :: TFinKp = 0.0_ReKi !< Tail fin potential lift coefficient for unsteady aerodynamics [used only when TFMod=2] [-] + REAL(ReKi) , DIMENSION(1:3) :: TFinSigma = 0.0_ReKi !< Tail fin empirical constants characterizing the decay of separation functions [used only when TFMod=2] [-] + REAL(ReKi) , DIMENSION(1:3) :: TFinAStar = 0.0_ReKi !< Tail fin characteristics angles for separation functions [used only when TFMod=2] [deg] + REAL(ReKi) :: TFinKv = 0.0_ReKi !< Tail fin vortex lift coefficient for unsteady aerodynamics [used only when TFMod=2] [-] + REAL(ReKi) :: TFinCDc = 0.0_ReKi !< Tail fin drag coefficient for unsteady aerodynamics [used only when TFMod=2] [-] END TYPE TFinInputFileType ! ======================= ! ========= AD_VTK_BLSurfaceType ======= @@ -514,6 +524,11 @@ subroutine AD_CopyTFinParameterType(SrcTFinParameterTypeData, DstTFinParameterTy DstTFinParameterTypeData%TFinArea = SrcTFinParameterTypeData%TFinArea DstTFinParameterTypeData%TFinIndMod = SrcTFinParameterTypeData%TFinIndMod DstTFinParameterTypeData%TFinAFID = SrcTFinParameterTypeData%TFinAFID + DstTFinParameterTypeData%TFinKp = SrcTFinParameterTypeData%TFinKp + DstTFinParameterTypeData%TFinSigma = SrcTFinParameterTypeData%TFinSigma + DstTFinParameterTypeData%TFinAStar = SrcTFinParameterTypeData%TFinAStar + DstTFinParameterTypeData%TFinKv = SrcTFinParameterTypeData%TFinKv + DstTFinParameterTypeData%TFinCDc = SrcTFinParameterTypeData%TFinCDc end subroutine subroutine AD_DestroyTFinParameterType(TFinParameterTypeData, ErrStat, ErrMsg) @@ -535,6 +550,11 @@ subroutine AD_PackTFinParameterType(RF, Indata) call RegPack(RF, InData%TFinArea) call RegPack(RF, InData%TFinIndMod) call RegPack(RF, InData%TFinAFID) + call RegPack(RF, InData%TFinKp) + call RegPack(RF, InData%TFinSigma) + call RegPack(RF, InData%TFinAStar) + call RegPack(RF, InData%TFinKv) + call RegPack(RF, InData%TFinCDc) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -548,6 +568,11 @@ subroutine AD_UnPackTFinParameterType(RF, OutData) call RegUnpack(RF, OutData%TFinArea); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TFinIndMod); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TFinAFID); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinKp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinSigma); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinAStar); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinKv); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinCDc); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine AD_CopyTFinInputFileType(SrcTFinInputFileTypeData, DstTFinInputFileTypeData, CtrlCode, ErrStat, ErrMsg) @@ -566,6 +591,11 @@ subroutine AD_CopyTFinInputFileType(SrcTFinInputFileTypeData, DstTFinInputFileTy DstTFinInputFileTypeData%TFinAngles = SrcTFinInputFileTypeData%TFinAngles DstTFinInputFileTypeData%TFinIndMod = SrcTFinInputFileTypeData%TFinIndMod DstTFinInputFileTypeData%TFinAFID = SrcTFinInputFileTypeData%TFinAFID + DstTFinInputFileTypeData%TFinKp = SrcTFinInputFileTypeData%TFinKp + DstTFinInputFileTypeData%TFinSigma = SrcTFinInputFileTypeData%TFinSigma + DstTFinInputFileTypeData%TFinAStar = SrcTFinInputFileTypeData%TFinAStar + DstTFinInputFileTypeData%TFinKv = SrcTFinInputFileTypeData%TFinKv + DstTFinInputFileTypeData%TFinCDc = SrcTFinInputFileTypeData%TFinCDc end subroutine subroutine AD_DestroyTFinInputFileType(TFinInputFileTypeData, ErrStat, ErrMsg) @@ -589,6 +619,11 @@ subroutine AD_PackTFinInputFileType(RF, Indata) call RegPack(RF, InData%TFinAngles) call RegPack(RF, InData%TFinIndMod) call RegPack(RF, InData%TFinAFID) + call RegPack(RF, InData%TFinKp) + call RegPack(RF, InData%TFinSigma) + call RegPack(RF, InData%TFinAStar) + call RegPack(RF, InData%TFinKv) + call RegPack(RF, InData%TFinCDc) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -604,6 +639,11 @@ subroutine AD_UnPackTFinInputFileType(RF, OutData) call RegUnpack(RF, OutData%TFinAngles); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TFinIndMod); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TFinAFID); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinKp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinSigma); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinAStar); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinKv); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TFinCDc); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine AD_CopyVTK_BLSurfaceType(SrcVTK_BLSurfaceTypeData, DstVTK_BLSurfaceTypeData, CtrlCode, ErrStat, ErrMsg) diff --git a/modules/aerodyn/src/BEMT.f90 b/modules/aerodyn/src/BEMT.f90 index c71362ca7f..b99c3a6658 100644 --- a/modules/aerodyn/src/BEMT.f90 +++ b/modules/aerodyn/src/BEMT.f90 @@ -126,7 +126,7 @@ subroutine BEMT_Set_UA_InitData( InitInp, interval, Init_UA_Data, errStat, errMs call move_alloc(InitInp%UAOff_outerNode, Init_UA_Data%UAOff_outerNode) Init_UA_Data%dt = interval - Init_UA_Data%OutRootName = InitInp%RootName ! was 'Debug.UA' + Init_UA_Data%OutRootName = trim(InitInp%RootName)//'.UA' Init_UA_Data%numBlades = InitInp%numBlades Init_UA_Data%nNodesPerBlade = InitInp%numBladeNodes @@ -137,6 +137,9 @@ subroutine BEMT_Set_UA_InitData( InitInp, interval, Init_UA_Data, errStat, errMs Init_UA_Data%ShedEffect = .true. ! This should be true when coupled to BEM Init_UA_Data%WrSum = InitInp%SumPrint + Init_UA_Data%UA_OUTS = 0 + Init_UA_Data%d_34_to_ac = 0.5_ReKi + end subroutine BEMT_Set_UA_InitData @@ -2322,6 +2325,11 @@ subroutine SetInputs_for_UA(BEM_Mod, phi, theta, cantAngle, toeAngle, axInductio call GetReynoldsNumber(BEM_Mod, axInduction, tanInduction, Vx, Vy, Vz, chord, kinVisc, theta, phi, cantAngle, toeAngle, u_UA%Re) endif + ! NOTE: + ! U: is here is the norm of the velocity made of Vx(1-a) and Vy(1+a'). + ! Ideally we would go back to the airfoil coordinate system + ! Below, v_ac is in the airfoil coordinate system. In baseline configurations, v_ac(1)>0 and v_ac(2)>0 + u_UA%v_ac(1) = sin(u_UA%alpha)*u_UA%U u_UA%v_ac(2) = cos(u_UA%alpha)*u_UA%U diff --git a/modules/aerodyn/src/FVW.f90 b/modules/aerodyn/src/FVW.f90 index ade7d76f1f..e501b2d9c7 100644 --- a/modules/aerodyn/src/FVW.f90 +++ b/modules/aerodyn/src/FVW.f90 @@ -1595,7 +1595,7 @@ subroutine UA_Init_Wrapper(AFInfo, InitInp, interval, p, x, xd, OtherState, m, E Init_UA_Data%c(i,1) = p%W(iW)%chord_LL(i) ! NOTE: InitInp chord move-allocd to p end do Init_UA_Data%dt = interval - Init_UA_Data%OutRootName = trim(InitInp%RootName)//'W'//num2lstr(iW) + Init_UA_Data%OutRootName = trim(InitInp%RootName)//'W'//num2lstr(iW)//'.UA' Init_UA_Data%numBlades = 1 Init_UA_Data%nNodesPerBlade = InitInp%numBladeNodes ! At AeroDyn ndoes, not CP @@ -1604,6 +1604,9 @@ subroutine UA_Init_Wrapper(AFInfo, InitInp, interval, p, x, xd, OtherState, m, E Init_UA_Data%a_s = InitInp%a_s ! Speed of sound, m/s Init_UA_Data%ShedEffect = .False. ! Important, when coupling UA wih vortex code, shed vorticity is inherently accounted for Init_UA_Data%WrSum = InitInp%SumPrint + Init_UA_Data%UA_OUTS = 0 + Init_UA_Data%d_34_to_ac = 0.5_ReKi + allocate(Init_UA_Data%UAOff_innerNode(1), stat=errStat2) allocate(Init_UA_Data%UAOff_outerNode(1), stat=errStat2) Init_UA_Data%UAOff_innerNode(1) = InitInp%W(iW)%UAOff_innerNode diff --git a/modules/aerodyn/src/FVW_Subs.f90 b/modules/aerodyn/src/FVW_Subs.f90 index f10b38f0a5..f2345493b3 100644 --- a/modules/aerodyn/src/FVW_Subs.f90 +++ b/modules/aerodyn/src/FVW_Subs.f90 @@ -130,10 +130,11 @@ subroutine ReadAndInterpGamma(CirculationFileName, s_CP_LL, L, Gamma_CP_LL, ErrS real(ReKi), parameter :: ReNaN = huge(1.0_ReKi) ErrStat = ErrID_None ErrMsg = '' + ! TODO Poentially use ReadDelimFile Instead ! --- call GetNewUnit(iUnit) call OpenFInpFile(iUnit, CirculationFileName, errStat2, errMsg2); if(Failed()) return - nLines=line_count(iUnit)-1 + nLines=line_count(iUnit, errStat2, errMsg2)-1 ! Read Header read(iUnit,*, iostat=errStat2) line ; if(Failed()) return ! Read table: s/L [-], GammaPresc [m^2/s] @@ -172,28 +173,6 @@ logical function Failed() if (Failed) call CleanUp() end function Failed - !> Counts number of lines in a file - integer function line_count(iunit) - integer(IntKi), intent(in) :: iunit - character(len=1054) :: line - ! safety for infinite loop.. - integer(IntKi), parameter :: nline_max=100000000 ! 100 M - integer(IntKi) :: i - line_count=0 - do i=1,nline_max - line='' - read(iunit,'(A)',END=100)line - line_count=line_count+1 - enddo - if (line_count==nline_max) then - print*,'Error: maximum number of line exceeded' - endif - 100 if(len(trim(line))>0) then - line_count=line_count+1 - endif - rewind(iunit) - end function - endsubroutine ReadAndInterpGamma ! ===================================================================================== diff --git a/modules/aerodyn/src/UA_Dvr_Subs.f90 b/modules/aerodyn/src/UA_Dvr_Subs.f90 index 0577387f87..066bde369e 100644 --- a/modules/aerodyn/src/UA_Dvr_Subs.f90 +++ b/modules/aerodyn/src/UA_Dvr_Subs.f90 @@ -5,21 +5,41 @@ module UA_Dvr_Subs use AirfoilInfo_Types use UnsteadyAero_Types use UnsteadyAero + use LinDyn + use LinDyn_Types implicit none - - type UA_Dvr_InitInput + integer, parameter :: NumAFfiles = 1 + integer(IntKi), parameter :: NumInp = 2 ! Number of inputs sent to UA_UpdateStates (must be at least 2) + integer(IntKi), parameter :: InflowMod_Cst = 1 ! Inflow is constant + integer(IntKi), parameter :: InflowMod_File = 2 ! Inflow is read from file + integer(IntKi), parameter, dimension(2) :: InflowMod_Valid = (/InflowMod_Cst, InflowMod_File/) + integer(IntKi), parameter :: MotionMod_Cst = 1 ! Motion is constant + integer(IntKi), parameter :: MotionMod_File = 2 ! Motion is read from file + integer(IntKi), parameter, dimension(2) :: MotionMod_Valid = (/MotionMod_Cst, MotionMod_File/) + real(ReKi), parameter :: myNaN = -9999.9_ReKi + integer(IntKi), parameter :: idFmt_Ascii = 1 + integer(IntKi), parameter :: idFmt_Binary = 2 + integer(IntKi), parameter :: idFmt_Both = 3 + integer(IntKi), parameter, dimension(3) :: idFmt_Valid = (/idFmt_Ascii, idFmt_Binary, idFmt_Both/) + + type Dvr_Parameters logical :: Echo + ! Environment + real(ReKi) :: KinVisc + real(ReKi) :: FldDens real(ReKi) :: SpdSound - character(1024) :: OutRootName - real(ReKi) :: InflowVel + ! integer :: UAMod logical :: Flookup logical :: UseCm character(1024) :: AirFoil1 real(ReKi) :: Chord + ! integer :: SimMod + ! Reduced frequency - SimMod = 1 + real(ReKi) :: InflowVel real(ReKi) :: NCycles real(ReKi) :: Frequency real(ReKi) :: Re @@ -27,516 +47,409 @@ module UA_Dvr_Subs real(ReKi) :: Amplitude real(ReKi) :: Mean integer :: Phase - character(1024) :: InputsFile + ! Prescribed Aero - SimMod = 2 + real(ReKi) :: TMax_PA + real(DbKi) :: dt_PA + character(1024) :: AeroTSFile + ! AeroElastic Section - SimMod =3 + real(ReKi) :: TMax + real(DbKi) :: dt + real(ReKi) :: MM(3,3) + real(ReKi) :: CC(3,3) + real(ReKi) :: KK(3,3) + logical :: activeDOFs(3) + real(ReKi) :: GFScaling(3,3) + real(ReKi) :: initPos(3) + real(ReKi) :: initVel(3) + real(ReKi) :: Vec_AQ(2) ! Vector from A to quarter chord /aerodynamic center + real(ReKi) :: Vec_AT(2) ! Vector from A to three quarter chord + real(ReKi) :: Twist ! Twist of the airfoil section (input deg, but stored in rad afterwards) + ! Inflow + integer :: InflowMod = InflowMod_Cst + real(ReKi) :: Inflow(2) + character(1024) :: InflowTSFile + ! Motion + integer :: MotionMod = MotionMod_Cst + character(1024) :: MotionTSFile + ! Outputs logical :: SumPrint logical :: WrAFITables - end type UA_Dvr_InitInput - - contains - - subroutine ReadDriverInputFile( inputFile, InitInp, ErrStat, ErrMsg ) + ! ---- Parameters + real(ReKi) :: d_34_to_ac + !real(DbKi) :: dt + real(DbKi) :: simTime + integer :: numSteps + character(1024) :: OutRootName ! Automatically obtained from input file name + ! Prescribed AoA simulations + real(DbKi), allocatable :: timeArr(:) + real(ReKi), allocatable :: vPrescrAero(:,:) ! Aero as function of time, shape nt x 4: Time, AOA, U, Omega + ! Prescribed inflow simulations + real(ReKi), allocatable :: vU0(:,:) ! Inflow as function of time, shape nt x 3 : Time, U0x, U0y + end type Dvr_Parameters - character(1024), intent( in ) :: inputFile - type(UA_Dvr_InitInput), intent( out ) :: InitInp - integer, intent( out ) :: ErrStat ! returns a non-zero value when an error occurs - character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - ! Local variables - integer :: UnIn ! Unit number for the input file - integer :: UnEchoLocal ! The local unit number for this module's echo file - character(1024) :: EchoFile ! Name of HydroDyn echo file - character(1024) :: FileName ! Name of HydroDyn input file - integer(IntKi) :: errStat2 ! Status of error message - character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None - character(*), parameter :: RoutineName = 'ReadDriverInputFile' + type :: Dvr_Outputs + integer(intki) :: unOutFile = -1 !< unit number for writing output file + !integer(intki) :: actualchanlen !< actual length of channels written to text file (less than or equal to chanlen) [-] + integer(intki) :: ny !< total number of outputs for the driver + integer(intki) :: ny_dvr !< number of outputs for the driver (without UA and LD, and Time) + integer(intki) :: ny_UA !< number of outputs for UA + integer(intki) :: ny_LD !< number of outputs for LD + !character(20) :: fmt_t !< format specifier for time channel [-] + !character(25) :: fmt_a !< format specifier for each column (including delimiter) [-] + !character(1) :: delim !< column delimiter [-] + !character(20) :: outfmt !< format specifier [-] + integer(intki) :: fileFmt = idFmt_Binary !< output format 1=text, 2=binary, 3=both [-] + character(1024) :: root = '' !< output file rootname [-] + character(ChanLen) , dimension(:), allocatable :: WriteOutputHdr !< channel headers [-] + character(ChanLen) , dimension(:), allocatable :: WriteOutputUnt !< channel units [-] + real(ReKi) , dimension(:,:), allocatable :: storage !< nchannel x ntime [-] + real(ReKi) , dimension(:), allocatable :: outline !< output line to be written to disk [-] + !real(dbki) :: dt_outs !< output time resolution [s] + !integer(intki) :: n_dt_out !< number of time steps between writing a line in the time-marching output files [-] + end type Dvr_Outputs - character(1024) :: PriPath ! the path to the primary input file - CALL GetPath( inputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + type :: Dvr_Misc + ! Reminder: + ! Q: 1/4 chord / aerodynamic center + ! T: 3/4 chord + ! A: Airfoil origin + real(ReKi) :: Vst_Q(2) !< Structural velocity at Q [m/s] + real(ReKi) :: Vst_T(2) !< Structural velocity at T [m/s] + real(ReKi) :: Vrel_Q(2) !< Relative velocity at Q [m/s] + real(ReKi) :: Vrel_T(2) !< Relative velocity at T [m/s] + real(ReKi) :: Vrel_norm2_T !< Squared velocity norm at T [m^2/s^2] + real(ReKi) :: Vrel_norm2_Q !< Squared velocity norm at Q [m^2/s^2] + real(ReKi) :: alpha_Q !< Angle of attack at Q [rad] + real(ReKi) :: alpha_T !< Angle of attack at T [rad] + real(ReKi) :: phi_Q !< Flow angle at Q [rad] + real(ReKi) :: phi_T !< Flow angle at T [rad] + real(ReKi) :: Re !< Reynolds number (NOT in Million!) + real(ReKi) :: L, D, tau_Q !< Aerodynamic loads at Q [N/m & Nm/m] + real(ReKi) :: FxA, FyA, tau_A !< Aerodynamic loads at A [N/m & Nm/m] + real(ReKi) :: GF(3) !< Generalized force, Scaled aerodynamic loads to be representative of the blade + real(ReKi) :: twist_full !< Full twist (includes initial twist, potential pitch, and torsion) + integer :: iU0Last = 1 !< Index for faster interpolation of wind speed + integer :: iPALast = 1 !< Index for faster interpolation of prescribed aero + real(ReKi) :: uPA(3) !< Prescribed Aero inputs + end type Dvr_Misc - - ! Initialize the echo file unit to -1 which is the default to prevent echoing, we will alter this based on user input - UnEchoLocal = -1 - ErrStat = ErrID_None - ErrMsg = '' - FileName = trim(inputFile) - - call GetNewUnit( UnIn ) - call OpenFInpFile( UnIn, FileName, errStat2, errMsg2 ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + type Dvr_Data + ! Time control + real(DbKi) :: uTimes(NumInp) + ! Parameters / initinp set as the same... + type(Dvr_Parameters) :: p ! Initialization/parameter data for the driver program + type(Dvr_Misc) :: m ! Misc variables for aerodynamic calculations + ! Outputs + type(Dvr_Outputs) :: out + ! Inflow + real(ReKi) :: U0(NumInp, 2) ! Inflow velocity vector at time t and t+dt + ! AFI + type(AFI_ParameterType) :: AFI_Params(NumAFfiles) + integer, allocatable :: AFIndx(:,:) + ! UA + type(UA_InitInputType) :: UA_InitInData ! Input data for initialization + type(UA_InitOutputType) :: UA_InitOutData ! Output data from initialization + type(UA_ContinuousStateType) :: UA_x ! Continuous states + type(UA_DiscreteStateType) :: UA_xd ! Discrete states + type(UA_OtherStateType) :: UA_OtherState ! Other/optimization states + type(UA_MiscVarType) :: UA_m ! Misc/optimization variables + type(UA_ParameterType) :: UA_p ! Parameters + type(UA_InputType) :: UA_u(NumInp) ! System inputs + type(UA_OutputType) :: UA_y ! System outputs + ! Dynamics + type(LD_InitInputType) :: LD_InitInData ! Input data for initialization + type(LD_InitOutputType) :: LD_InitOutData ! Output data from initialization + type(LD_ContinuousStateType) :: LD_x ! Continuous states + type(LD_DiscreteStateType) :: LD_xd ! Discrete states + type(LD_OtherStateType) :: LD_OtherState ! Other/optimization states + type(LD_ConstraintStateType) :: LD_z ! Constraint states + type(LD_MiscVarType) :: LD_m ! Misc/optimization variables + type(LD_ParameterType) :: LD_p ! Parameters + type(LD_InputType) :: LD_u(NumInp) ! System inputs + type(LD_OutputType) :: LD_y ! System outputs + ! + type(LD_ContinuousStateType) :: LD_x_swp ! Continuous states + type(LD_OtherStateType) :: LD_OtherState_swp ! Other/optimization states + type(UA_ContinuousStateType) :: UA_x_swp ! Continuous states + type(UA_DiscreteStateType) :: UA_xd_swp ! Discrete states + type(UA_OtherStateType) :: UA_OtherState_swp ! Other/optimization states + end type Dvr_Data +contains - call WrScr( ' Opening UnsteadyAero Driver input file: '//FileName ) - - - !------------------------------------------------------------------------------------------------- - ! File header - !------------------------------------------------------------------------------------------------- - - call ReadCom( UnIn, FileName, ' UnsteadyAero Driver input file header line 1', errStat2, errMsg2 ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if +!-------------------------------------------------------------------------------------------------------------- +subroutine ReadDriverInputFile( FileName, InitInp, ErrStat, ErrMsg ) + character(1024), intent( in ) :: filename + type(Dvr_Parameters), intent( out ) :: InitInp + integer, intent( out ) :: ErrStat ! returns a non-zero value when an error occurs + character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! Local variables + integer :: UnEcho ! The local unit number for this module's echo file + integer :: iLine + character(1024) :: EchoFile ! Name of HydroDyn echo file + character(1024) :: PriPath ! the path to the primary input file + character(1024) :: Line ! the path to the primary input file + type(FileInfoType) :: FI !< The derived type for holding the file information. + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'ReadDriverInputFile' + ! Initialize the echo file unit to -1 which is the default to prevent echoing, we will alter this based on user input + UnEcho = -1 + ErrStat = ErrID_None + ErrMsg = '' + ! Read all input file lines into fileinfo + call WrScr(' Opening UnsteadyAero Driver input file: '//trim(FileName) ) + call ProcessComFile(FileName, FI, errStat2, errMsg2); if (Failed()) return + CALL GetPath( FileName, PriPath ) ! Input files will be relative to the path where the primary input file is located. + !call GetRoot(FileName, dvr%root) - call ReadCom( UnIn, FileName, 'UnsteadyAero Driver input file header line 2', errStat2, errMsg2 ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + ! --- Header and echo + iLine = 3 ! Skip the first two lines as they are known to be header lines and separators + call ParseVar(FI, iLine, 'Echo', InitInp%Echo, errStat2, errMsg2); if (Failed()) return; + if ( InitInp%Echo ) then + EchoFile = trim(FileName)//'.ech' + call OpenEcho (UnEcho, EchoFile, errStat2, errMsg2 ); if(Failed()) return + do iLine = 1, 3 + write(UnEcho, '(A)') trim(FI%Lines(iLine)) + enddo + end if + iLine = 4 + ! --- Environmental conditions section + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'FldDens', InitInp%FldDens , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'KinVisc', InitInp%KinVisc , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'SpdSound', InitInp%SpdSound, errStat2, errMsg2, UnEcho); if(Failed()) return + + ! --- UNSTEADYAERO section + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'UAMod' , InitInp%UAMod , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'Flookup' , InitInp%Flookup , errStat2, errMsg2, UnEcho); if(Failed()) return - ! Echo Input Files. - - call ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo Input', errStat2, errMsg2 ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - + ! --- AIRFOIL PROPERTIES section + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'AirFoil' , InitInp%AirFoil1, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'Chord' , InitInp%Chord , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'Vec_AQ' , InitInp%Vec_AQ , 2, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'Vec_AT' , InitInp%Vec_AT , 2, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'UseCm' , InitInp%UseCm , errStat2, errMsg2, UnEcho); if(Failed()) return - ! If we are Echoing the input then we should re-read the first three lines so that we can echo them - ! using the NWTC_Library routines. The echoing is done inside those routines via a global variable - ! which we must store, set, and then replace on error or completion. - - if ( InitInp%Echo ) then - - EchoFile = TRIM(FileName)//'.ech' - call GetNewUnit( UnEchoLocal ) - call OpenEcho ( UnEchoLocal, EchoFile, errStat2, errMsg2 ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - rewind(UnIn) - - call ReadCom( UnIn, FileName, 'UnsteadyAero Driver input file header line 1', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + ! --- SIMULATION CONTROL section + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'SimMod' , InitInp%SimMod , errStat2, errMsg2, UnEcho); if(Failed()) return + ! --- REDUCED FREQUENCY + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'InflowVel' , InitInp%InflowVel , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'NCycles' , InitInp%NCycles , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'StepsPerCycle', InitInp%StepsPerCycle, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'Frequency' , InitInp%Frequency , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'Amplitude' , InitInp%Amplitude , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'Mean' , InitInp%Mean , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'Phase' , InitInp%Phase , errStat2, errMsg2, UnEcho); if(Failed()) return - call ReadCom( UnIn, FileName, 'UnsteadyAero Driver input file header line 2', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + ! --- PRESCRIBED AERO section + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'TMax_PA' , InitInp%Tmax_PA , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'DT_PA' , InitInp%dt_PA , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'AeroTSFile' , InitInp%AeroTSFile , errStat2, errMsg2, UnEcho); if(Failed()) return - - ! Echo Input Files. Note this line is prevented from being echoed by the ReadVar routine. - - call ReadVar ( UnIn, FileName, InitInp%Echo, 'Echo', 'Echo the input file data', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - end if - - !------------------------------------------------------------------------------------------------- - ! Environmental conditions section - !------------------------------------------------------------------------------------------------- + ! --- ELASTIC SECTION section + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'TMax' , InitInp%Tmax , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'DT' , InitInp%dt , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'activeDOFs' , InitInp%activeDOFs, 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'initPos' , InitInp%initPos , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'initVel' , InitInp%initVel , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'GFScaling1' , InitInp%GFScaling(1,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'GFScaling2' , InitInp%GFScaling(2,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'GFScaling3' , InitInp%GFScaling(3,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'MassMatrix1' , InitInp%MM(1,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'MassMatrix2' , InitInp%MM(2,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'MassMatrix3' , InitInp%MM(3,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'DampMatrix1' , InitInp%CC(1,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'DampMatrix2' , InitInp%CC(2,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'DampMatrix3' , InitInp%CC(3,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'StifMatrix1' , InitInp%KK(1,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'StifMatrix2' , InitInp%KK(2,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'StifMatrix3' , InitInp%KK(3,:) , 3, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'Twist' , InitInp%Twist , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'InflowMod' , InitInp%InflowMod , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseAry(FI, iLine, 'Inflow' , InitInp%Inflow , 2, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'InflowTSFile' , InitInp%InflowTSFile, errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'MotionMod' , InitInp%MotionMod , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'MotionTSFile' , InitInp%MotionTSFile, errStat2, errMsg2, UnEcho); if(Failed()) return - ! Header - - call ReadCom( UnIn, FileName, 'Environmental conditions header', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + ! --- OUTPUT section + call ParseCom(FI, iLine, Line , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'SumPrint' , InitInp%SumPrint , errStat2, errMsg2, UnEcho); if(Failed()) return + call ParseVar(FI, iLine, 'WrAFITables', InitInp%WrAFITables, errStat2, errMsg2, UnEcho); if(Failed()) return + ! --- Triggers + call GetRoot(FileName, InitInp%OutRootName) ! OutRootName is inferred from current filename. + !InitInp%OutRootName=trim(InitInp%OutRootName)//'.UA' ! For backward compatibility + !if (PathIsRelative(InitInp%OutRootName)) InitInp%OutRootName = TRIM(PriPath)//TRIM(InitInp%OutRootName) + if (PathIsRelative(InitInp%Airfoil1)) InitInp%Airfoil1 = TRIM(PriPath)//TRIM(InitInp%Airfoil1) + if (PathIsRelative(InitInp%AeroTSFile )) InitInp%AeroTSFile = TRIM(PriPath)//TRIM(InitInp%AeroTSFile ) + if (PathIsRelative(InitInp%InflowTSFile )) InitInp%InflowTSFile = TRIM(PriPath)//TRIM(InitInp%InflowTSFile) + if (PathIsRelative(InitInp%MotionTSFile )) InitInp%MotionTSFile = TRIM(PriPath)//TRIM(InitInp%MotionTSFile) - ! SpdSound - Speed of Sound. - - call ReadVar ( UnIn, FileName, InitInp%SpdSound, 'SpdSound', 'SpdSound', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + ! --- Checks + !if (Check(.not.(any(dvr%out%fileFmt==idFmt_Valid )), 'FileFormat not implemented: '//trim(Num2LStr(InitInp%InflowMod)))) return + if (Check(.not.(any(InitInp%InflowMod==InflowMod_Valid)), 'InflowMod not implemented: '//trim(Num2LStr(InitInp%MotionMod)))) return + if (Check(.not.(any(InitInp%MotionMod==MotionMod_Valid)), 'MotionMod not implemented: '//trim(Num2LStr(InitInp%MotionMod)))) return + if (InitInp%SimMod==3) then ! Temporary to avoid changing r-test for now + !if (Check(.not.EqualRealNos(InitInp%MM(1,1), InitInp%MM(2,2), 'Mass matrix entries 11 and 22 should match.') return - - !------------------------------------------------------------------------------------------------- - ! UNSTEADYAERO section - !------------------------------------------------------------------------------------------------- + if (InitInp%Vec_AT(2)<0) call WrScr('[WARN] Vec_AT(2) is negative, but this value is usually positive (for A between T and Q)') + if (InitInp%Vec_AQ(2)>0) call WrScr('[WARN] Vec_AQ(2) is positive, but this value is usually negative (for A between T and Q)') + endif - ! Header - - call ReadCom( UnIn, FileName, 'UNSTEADYAERO header', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + call Cleanup() +contains + logical function Failed() + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + Failed = ErrStat >= AbortErrLev + if (Failed) call Cleanup() + end function Failed - - ! OutRootName - call ReadVar ( UnIn, FileName, InitInp%OutRootName, 'OutRootName', & - 'UnsteadyAero output root filename', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - if (PathIsRelative(InitInp%OutRootName)) InitInp%OutRootName = TRIM(PriPath)//TRIM(InitInp%OutRootName) - - ! InflowVel - - call ReadVar ( UnIn, FileName, InitInp%InflowVel, 'InflowVel', & - 'Inflow velocity', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! Re - - call ReadVar ( UnIn, FileName, InitInp%Re, 'Re', & - 'Reynolds number in millions', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! UAMod - call ReadVar ( UnIn, FileName, InitInp%UAMod, 'UAMod', & - 'Unsteady Aero Model Switch', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! Flookup - call ReadVar ( UnIn, FileName, InitInp%Flookup, 'Flookup', & - "Lookup used to determine f'", errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - - - - !------------------------------------------------------------------------------------------------- - ! AIRFOIL PROPERTIES section - !------------------------------------------------------------------------------------------------- + subroutine Cleanup() + ! Close this module's echo file + if ( InitInp%Echo ) then + close(UnEcho) + end if + Call NWTC_Library_Destroyfileinfotype(FI, errStat2, errMsg2) + end subroutine Cleanup - ! Header - - call ReadCom( UnIn, FileName, 'AIRFOIL PROPERTIES header', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - - - ! AirFoil1 - - call ReadVar ( UnIn, FileName, InitInp%AirFoil1, 'AirFoil1', & - 'Filename for the airfoil table and properties', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - if (PathIsRelative(InitInp%Airfoil1)) InitInp%Airfoil1 = TRIM(PriPath)//TRIM(InitInp%Airfoil1) - - ! Chord - - call ReadVar ( UnIn, FileName, InitInp%Chord, 'Chord', & - 'Chord length', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! Using Cm column - call ReadVar ( UnIn, FileName, InitInp%UseCm, 'UseCm', & - "Using Cm Airfoil table data", errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - !------------------------------------------------------------------------------------------------- - ! SIMULATION CONTROL section - !------------------------------------------------------------------------------------------------- + logical function Check(Condition, errMsg_in) + logical, intent(in) :: Condition + character(len=*), intent(in) :: errMsg_in + Check=Condition + if (Check) then + call SetErrStat( ErrID_Fatal, errMsg_in, errStat, errMsg, RoutineName ) + endif + end function Check - ! Header - - call ReadCom( UnIn, FileName, 'SIMULATION CONTROL header', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - - ! SimMod - call ReadVar ( UnIn, FileName, InitInp%SimMod, 'SimMod', & - 'Simulation model', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! NCycles - call ReadVar ( UnIn, FileName, InitInp%NCycles, 'NCycles', & - 'Number of cycles for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! StepsPerCycle - call ReadVar ( UnIn, FileName, InitInp%StepsPerCycle, 'StepsPerCycle', & - 'Number of timesteps per cycle', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! Frequency - call ReadVar ( UnIn, FileName, InitInp%Frequency, 'Frequency', & - 'Frequency of angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! Amplitude - call ReadVar ( UnIn, FileName, InitInp%Amplitude, 'Amplitude', & - 'Amplitude for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! Mean - call ReadVar ( UnIn, FileName, InitInp%Mean, 'Mean', & - 'Mean for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - ! Phase - call ReadVar ( UnIn, FileName, InitInp%Phase, 'Phase', & - 'Initial phase for angle-of-attack inputs', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if +end subroutine ReadDriverInputFile +!-------------------------------------------------------------------------------------------------------------- +subroutine Dvr_SetParameters(p, errStat, errMsg) + type(Dvr_Parameters), intent(inout) :: p + integer, intent(out ) :: errStat ! returns a non-zero value when an error occurs + character(*), intent(out ) :: errMsg ! Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + errStat2= ErrID_None + errStat = ErrID_None + errMsg = '' + ! Unit conversions + p%Twist = p%Twist * D2R + p%d_34_to_ac = (-p%Vec_AQ(2) + p%Vec_AT(2)) ! d_34_to_ac = d_QT ~0.5 [-], Approximated using y coordinate + p%Vec_AT = p%Vec_AT * p%chord + p%Vec_AQ = p%Vec_AQ * p%chord + + if ( p%SimMod == 1 ) then + call WrScr('[WARN] The behavior of SimMod=1 might change in the future.') + + ! We will use a constant Reynolds.. + p%Re = p%InflowVel * p%chord/ p%KinVisc ! NOT IN MILLIONS + print*,' Re ',p%Re + ! Using the frequency and NCycles, determine how long the simulation needs to run + p%simTime = p%NCycles/p%Frequency + p%numSteps = p%StepsPerCycle*p%NCycles ! we could add 1 here to make this a complete cycle + p%dt = p%simTime / p%numSteps - ! InputsFile - call ReadVar ( UnIn, FileName, InitInp%InputsFile, 'InputsFile', & - 'Filename for Time series data in an ASCII input file', errStat2, errMsg2, UnEchoLocal ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - - !------------------------------------------------------------------------------------------------- - ! OUTPUT section - !------------------------------------------------------------------------------------------------- - call ReadCom( UnIn, FileName, 'Output conditions header', errStat2, errMsg2, UnEchoLocal ); if(Failed()) return - call ReadVar( UnIn, FileName, InitInp%SumPrint, 'SumPrint', 'Write unsteady aerodynamic summary file', errStat2, errMsg2, UnEchoLocal ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - call ReadVar( UnIn, FileName, InitInp%WrAFITables, 'WrAFITables', 'Write airfoil coefficients used by Airfoil Info', errStat2, errMsg2, UnEchoLocal ); call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - ! Temporarily allowing backward compatibility.. - call WrScr('') - call WrScr('[WARN] An error occured when reading the output section of the UA Driver input file.') - call WrScr(' Make sure it is at the latest version. See error message below:') - call WrScr(trim(ErrMsg)) - call WrScr('') - call WrScr('[INFO] Continuing using default output options.') - call WrScr('') - InitInp%SumPrint = .True. - InitInp%WrAFITables = .True. - ErrStat = ErrID_None - ErrMsg = '' + else if ( p%SimMod == 2 ) then + ! Read time-series data file with columns:( time, Angle-of-attack, Vrel, omega ) + call WrScr( ' Opening prescribed-aero time-series input file: '//trim(p%AeroTSFile) ) + call ReadDelimFile(p%AeroTSFile, 4, p%vPrescrAero, errStat2, errMsg2); if(Failed()) return + p%vPrescrAero(:,2) = p%vPrescrAero(:,2)*D2R ! Deg 2 rad + p%dt = p%dt_PA + p%simTime = p%TMax_PA + p%numSteps = int(p%simTime/p%dt) + + elseif ( p%SimMod == 3 ) then + p%simTime = p%TMax + p%numSteps = int(p%simTime/p%dt) + + if (p%InflowMod==InflowMod_File) then + ! Read inflow file + call ReadDelimFile(p%InflowTSFile, 3, p%vU0, errStat2, errMsg2); if(Failed()) return endif - call Cleanup() - contains - logical function Failed() - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - Failed = ErrStat >= AbortErrLev - if (Failed) call Cleanup() - end function Failed - subroutine Cleanup() - ! Close this module's echo file - if ( InitInp%Echo ) then - close(UnEchoLocal) - end if - close( UnIn ) - end subroutine Cleanup - end subroutine ReadDriverInputFile - - subroutine ReadTimeSeriesData( inputsFile, nSimSteps, timeArr, AOAarr, Uarr, OmegaArr, ErrStat, ErrMsg ) - character(1024), intent( in ) :: inputsFile - integer, intent( out ) :: nSimSteps - real(DbKi),allocatable, intent( out ) :: timeArr(:) - real(ReKi),allocatable, intent( out ) :: AOAarr(:) - real(ReKi),allocatable, intent( out ) :: Uarr(:) !RRD - real(ReKi),allocatable, intent( out ) :: OmegaArr(:) - integer, intent( out ) :: ErrStat ! returns a non-zero value when an error occurs - character(*), intent( out ) :: ErrMsg ! Error message if ErrStat /= ErrID_None - - real(SiKi) :: dt - real(DbKi) :: tmpArr(4) - integer(IntKi) :: errStat2 ! Status of error message - character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None - character(*), parameter :: RoutineName = 'ReadTimeSeriesData' - character(1024) :: FileName - integer :: UnIn - integer :: i - integer, PARAMETER ::hdrlines=8 ! RRD - - ErrStat = ErrID_None - ErrMsg = '' - nSimSteps = 0 ! allocate here in case errors occur - - FileName = trim(inputsFile) - - call GetNewUnit( UnIn ) - call OpenFInpFile( UnIn, FileName, errStat2, errMsg2 ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + endif + if(Failed()) return +contains + logical function Failed() + call setErrStat(errStat2, errMsg2, errStat, errMsg, 'Dvr_SetParameters') + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine Dvr_SetParameters +!-------------------------------------------------------------------------------------------------------------- +subroutine driverInputsToUAInitData(p, InitInData, AFI_Params, AFIndx, errStat, errMsg) + type(Dvr_Parameters) , intent(in ) :: p ! Initialization data for the driver program + type(UA_InitInputType) , intent(out) :: InitInData ! Input data for initialization + type(AFI_ParameterType), intent(out) :: AFI_Params(NumAFfiles) + integer, allocatable , intent(out) :: AFIndx(:,:) + integer(IntKi), intent(out) :: errStat ! Error status. + character(*), intent(out) :: errMsg ! Error message. + logical :: UA_f_cn ! Should the separation function be computed using Cn or Cl + character(1024) :: afNames(NumAFfiles) + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + character(*), parameter :: RoutineName = 'driverInputsToUAInitData' + errStat = ErrID_None + errMsg = '' + InitInData%UA_OUTS = 1 ! 0=None, 1=Write Outputs, 2=Separate File +#ifdef ADD_UA_OUTS + InitInData%UA_OUTS = 2 ! Compiler Flag Override, 2=Write a separate file +#endif - call WrScr( ' Opening UnsteadyAero time-series input file: '//FileName ) - - - !------------------------------------------------------------------------------------------------- - ! Determine how many lines of data are in the file: - !------------------------------------------------------------------------------------------------- - do i=1,hdrlines !RRD - call ReadCom( UnIn, FileName, ' UnsteadyAero time-series input file header line 1', errStat2, errMsg2 ) - call SetErrStat(errStat2, errMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - enddo - - do - call ReadAry( UnIn, FileName, tmpArr, 4, 'Data', 'Time-series data', errStat2, errMsg2 ) - ! The assumption is that the only parsing error occurs at the end of the file and therefore we stop reading data - if (errStat2 > ErrID_None) then - exit - else - nSimSteps = nSimSteps + 1 - end if - end do - - !------------------------------------------------------------------------------------------------- - ! Allocate arrays to be read - !------------------------------------------------------------------------------------------------- - allocate ( timeArr( nSimSteps ), STAT=ErrStat2 ) - if ( ErrStat2 /= 0 ) then - call SetErrStat( ErrID_Fatal, 'Error trying to allocate timeArr.', ErrStat, ErrMsg, RoutineName) - call Cleanup() - return - end if - - allocate ( AOAarr( nSimSteps ), STAT=ErrStat2 ) - if ( ErrStat2 /= 0 ) then - call SetErrStat( ErrID_Fatal, 'Error trying to allocate AOAarr.', ErrStat, ErrMsg, RoutineName) - call Cleanup() - return - end if - allocate ( Uarr( nSimSteps ), OmegaArr( nSimSteps ), STAT=ErrStat2 ) - if ( ErrStat2 /= 0 ) then - call SetErrStat( ErrID_Fatal, 'Error trying to allocate Uarr and OmegaArr.', ErrStat, ErrMsg, RoutineName) - call Cleanup() - return - end if - - - !------------------------------------------------------------------------------------------------- - ! Read arrays from file - !------------------------------------------------------------------------------------------------- - rewind(UnIn) - do i=1,hdrlines !RRD - call ReadCom( UnIn, FileName, ' UnsteadyAero time-series input file header line 1', errStat2, errMsg2 ) - enddo - do i = 1,nSimSteps - call ReadAry( UnIn, FileName, tmpArr, 4, 'Data', 'Time-series data', errStat2, errMsg2 ) - timeArr(i) = tmpArr(1) - AOAarr(i) = real(tmpArr(2),ReKi) - Uarr(i) = real(tmpArr(3),ReKi) - OmegaArr(i) = real(tmpArr(4),ReKi) - end do - - if (nSimSteps > 1) then - dt = timeArr(2) - timeArr(1) - - do i = 2,nSimSteps-1 - if (.not. EqualRealNos(dt, REAL(timeArr(i+1)-timeArr(i), SiKi) ) ) then - call SetErrStat( ErrID_Fatal, 'Times in InputsFile must be contain the same delta t.', ErrStat, ErrMsg, RoutineName) - exit !exit the do loop - end if - end do - end if - - call Cleanup() - - contains - !==================================================================================================== - subroutine Cleanup() - ! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to - ! any existing echo information - !---------------------------------------------------------------------------------------------------- - ! logical, intent( in ) :: EchoFlag ! local version of echo flag - ! integer, intent( in ) :: UnEcho ! echo unit number - - ! Close this module's echo file - - - close( UnIn ) - - end subroutine Cleanup - end subroutine ReadTimeSeriesData -!-------------------------------------------------------------------------------------------------------------- - subroutine Init_AFI(UAMod, NumAFfiles, afNames, UseCm, UA_f_cn, AFI_Params, ErrStat, ErrMsg) + ! -- UA Init Input Data + InitInData%nNodesPerBlade = 1 + InitInData%numBlades = 1 + call AllocAry(InitInData%c, InitInData%nNodesPerBlade, InitInData%numBlades, 'chord', errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInData%UAOff_innerNode , InitInData%numBlades, 'UAO' , errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInData%UAOff_outerNode , InitInData%numBlades, 'UAO' , errStat2, errMsg2); if(Failed()) return + + ! don't turn off UA based on span location: + InitInData%UAOff_innerNode = 0 + InitInData%UAOff_outerNode = InitInData%nNodesPerBlade + 1 + InitInData%a_s = p%SpdSound + InitInData%c(1,1) = p%Chord + InitInData%UAMod = p%UAMod + InitInData%Flookup = p%Flookup + InitInData%OutRootName = trim(p%OutRootName)//'.UA' + InitInData%WrSum = p%SumPrint + InitInData%d_34_to_ac = p%d_34_to_ac ! d_34_to_ac = d_QT ~0.5 [-], Approximated using y coordinate + + ! --- AFI + allocate(AFIndx(InitInData%nNodesPerBlade,InitInData%numBlades), STAT = errStat2) + if ( errStat2 /= 0 ) then + call SetErrStat( ErrID_Fatal, 'Error trying to allocate InitInData%AFIndx.', errStat, errMsg, RoutineName) + return + end if + AFIndx(1,1) = 1 + + UA_f_cn = (InitInData%UAMod /= UA_HGM).and.(InitInData%UAMod /= UA_OYE) ! HGM and OYE use the separation function based on cl instead of cn + afNames(1) = p%AirFoil1 ! All nodes/blades are using the same 2D airfoil + call Init_AFI( InitInData%UAMod, NumAFfiles, afNames, p%UseCm, UA_f_cn, AFI_Params, errStat2, errMsg2); if(Failed()) return + + if (p%WrAFITables) then + call WriteAFITables(AFI_Params(1), p%OutRootName, p%UseCm, UA_f_cn) + endif +contains + logical function Failed() + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + Failed = ErrStat >= AbortErrLev + end function Failed +endsubroutine driverInputsToUAInitData +!-------------------------------------------------------------------------------------------------------------- +subroutine Init_AFI(UAMod, NumAFfiles, afNames, UseCm, UA_f_cn, AFI_Params, ErrStat, ErrMsg) integer, intent(in ) :: UAMod integer, intent(in ) :: NumAFfiles CHARACTER(1024), intent(in ) :: afNames(NumAFfiles) @@ -552,16 +465,10 @@ subroutine Init_AFI(UAMod, NumAFfiles, afNames, UseCm, UA_f_cn, AFI_Params, ErrS integer(IntKi) :: errStat2 ! Status of error message character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None character(*), parameter :: RoutineName = 'Init_AFI' - - ! Initialize the Airfoil Info module - ! Setup Airfoil info - + UnEc = 0 - ErrStat = ErrID_None ErrMsg = "" - - ! Set this to 1 to use the UA coefs !AFI_InitInputs%UA_Model = 1 ! This is the number of columns of coefs in the AOA table: Cl, Cd, Cm, for example, but doesn't include Alpha @@ -575,15 +482,15 @@ subroutine Init_AFI(UAMod, NumAFfiles, afNames, UseCm, UA_f_cn, AFI_Params, ErrS else AFI_InitInputs%InCol_Cm = 0 end if - + AFI_InitInputs%InCol_Cpmin = 0 AFI_InitInputs%AFTabMod = AFITable_1 ! 1D-interpolation (on AoA only) AFI_InitInputs%UA_f_cn = UA_f_cn - + do i=1,NumAFfiles AFI_InitInputs%FileName = afNames(i) !InitInp%AF_File(i) - ! Call AFI_Init to read in and process the airfoil files. + ! Read in and process the airfoil files. ! This includes creating the spline coefficients to be used for interpolation. call AFI_Init ( AFI_InitInputs, AFI_Params(i), errStat2, errMsg2, UnEc ) @@ -595,128 +502,625 @@ subroutine Init_AFI(UAMod, NumAFfiles, afNames, UseCm, UA_f_cn, AFI_Params, ErrS end do call Cleanup() - - - contains - - !==================================================================================================== - subroutine Cleanup() - ! The routine cleans up data arrays framework structures - ! - !---------------------------------------------------------------------------------------------------- - !Clean up initialization inputs - call AFI_DestroyInitInput(AFI_InitInputs, errStat2, errMsg2) - - - - end subroutine Cleanup - end subroutine Init_AFI - - - subroutine WriteAFITables(AFI_Params, OutRootName, UseCm, UA_f_cn) - - type(AFI_ParameterType), intent(in), target :: AFI_Params - character(len=*) , intent(in) :: OutRootName - logical , intent(in) :: UseCm - logical , intent(in) :: UA_f_cn - - integer(IntKi) :: unOutFile - integer(IntKi) :: ErrStat - character(ErrMsgLen) :: ErrMsg - - Real(ReKi), allocatable :: cl_smooth(:) - Real(ReKi), allocatable :: cn_smooth(:) - Real(ReKi), allocatable :: cn(:) - Real(ReKi), allocatable :: cl_lin(:) - Real(ReKi), allocatable :: cn_lin(:) - character(len=3) :: Prefix - character(len=11) :: sFullyAtt - character(len=8) :: sCm - integer :: iTab, iRow, iStartUA - type(AFI_Table_Type), pointer :: tab !< Alias - - if (UA_f_cn) then - Prefix='Cn_' - sFullyAtt='Cn_FullyAtt' + +contains + subroutine Cleanup() + call AFI_DestroyInitInput(AFI_InitInputs, errStat2, errMsg2) + end subroutine Cleanup +end subroutine Init_AFI +!-------------------------------------------------------------------------------------------------------------- +!> Set Inflow inputs +subroutine setInflow(t, p, U0, m) + real(DbKi), intent(in) :: t + type(Dvr_Parameters), intent(in) :: p + type(Dvr_Misc ), intent(inout) :: m + real(ReKi), dimension(:), intent(out) :: U0 + if (p%InflowMod == InflowMod_Cst) then + U0(:) = p%Inflow + else if (p%InflowMod == InflowMod_File) then + call interpTimeValue(p%vU0, t, m%iU0Last, U0(:)) + else + print*,'Should never happen' + STOP + endif +end subroutine setInflow +!-------------------------------------------------------------------------------------------------------------- +!> Compute aerodynamic kinematics quantities (velocities and angles) at different points +subroutine AeroKinematics(U0, q, qd, p, m) + real(ReKi), intent(in) :: U0(2) !< Free stream + real(ReKi), intent(in) :: q(3) !< Elastic positions x,y,th + real(ReKi), intent(in) :: qd(3) !< Elastic velocities + type(Dvr_Parameters), intent(in ) :: p !< Parameters + type(Dvr_Misc), intent(inout) :: m !< Misc aero var + real(ReKi), parameter :: W(2) =0 ! Induced velocities + real(ReKi) :: ST, CT + + ! Full twist + m%twist_full = q(3) + p%Twist ! + Pitch if a controller is added + ST = sin(m%twist_full) + CT = cos(m%twist_full) + + ! Structual velocity including torsional velocity + m%Vst_T(1) = qd(1) + qd(3) * (-p%Vec_AT(1)*ST + p%Vec_AT(2)*CT) + m%Vst_T(2) = qd(2) + qd(3) * ( p%Vec_AT(1)*CT + p%Vec_AT(2)*ST) + + m%Vst_Q(1) = qd(1) + qd(3) * (-p%Vec_AQ(1)*ST + p%Vec_AQ(2)*CT) + m%Vst_Q(2) = qd(2) + qd(3) * ( p%Vec_AQ(1)*CT + p%Vec_AQ(2)*ST) + + ! Relative velocity, Vrel = U0 - Vst + W + m%Vrel_T = U0 - m%Vst_T + W + m%Vrel_Q = U0 - m%Vst_Q + W + + ! Squared velocity norm + m%Vrel_norm2_T = m%Vrel_T(1)**2 + m%Vrel_T(2)**2 + m%Vrel_norm2_Q = m%Vrel_Q(1)**2 + m%Vrel_Q(2)**2 + + ! Flow angle + m%phi_Q = atan2(m%Vrel_Q(1), m%Vrel_Q(2)) + m%phi_T = atan2(m%Vrel_T(1), m%Vrel_T(2)) + + ! Angle of attack + m%alpha_Q = m%phi_Q - m%twist_full + m%alpha_T = m%phi_T - m%twist_full + + ! Reynolds at 1/4 chord + m%Re = sqrt(m%Vrel_norm2_Q) * p%chord / p%KinVisc +end subroutine AeroKinematics + +!-------------------------------------------------------------------------------------------------------------- +!> Compute aerodynamic kinetics quantities (loads) +subroutine AeroKinetics(U0, q, qd, C_dyn, p, m) + real(ReKi), intent(in) :: U0(2) !< Free stream + real(ReKi), intent(in) :: q(3) !< Elastic positions x,y,th + real(ReKi), intent(in) :: qd(3) !< Elastic velocities + real(ReKi), intent(in) :: C_dyn(3) !< Dynamic aerodynamic coefficients (Cl, Cd, Cm) + type(Dvr_Parameters), intent(in ) :: p !< Parameters + type(Dvr_Misc), intent(inout) :: m !< Misc aero var + real(ReKi) :: ST, CT + real(ReKi) :: SP, CP + real(ReKi) :: q_dyn + + ! First get kinematics + call AeroKinematics(U0, q, qd, p, m) + + ST = sin(m%twist_full) + CT = cos(m%twist_full) + + ! Loads at Q + q_dyn = 0.5_ReKi * p%FldDens * p%chord * m%Vrel_norm2_Q + m%L = q_dyn * C_dyn(1) + m%D = q_dyn * C_dyn(2) + m%tau_Q = q_dyn * C_dyn(3) * p%chord + + ! Loads at A + SP = sin(m%phi_Q) + CP = cos(m%phi_Q) + m%FxA = m%L * CP + m%D * SP + m%FyA = -m%L * SP + m%D * CP + ! Tau A (Positive about "z") - version 1 + m%tau_A = m%tau_Q + m%tau_A = m%tau_A - m%FxA * (- p%Vec_AQ(1) * ST + p%Vec_AQ(2) * CT) + m%tau_A = m%tau_A + m%FyA * ( p%Vec_AQ(1) * CT + p%Vec_AQ(2) * ST) + ! Tau A (Positive about "z") - version 2 + !SA = sin(m%alpha_Q) + !CA = cos(m%alpha_Q) + !tau_A2 = m%tau_Q + !tau_A2 = tau_A2 - q_dyn *C_dyn(1)* ( p%Vec_AQ(1) * SA + p%Vec_AQ(2) * CA) + !tau_A2 = tau_A2 + q_dyn *C_dyn(2)* ( p%Vec_AQ(1) * CA - p%Vec_AQ(2) * SA) + + ! Generalized loads + m%GF(1) = m%FxA * p%GFScaling(1,1) + m%FyA * p%GFScaling(1,2) - m%tau_A * p%GFScaling(1,3) + m%GF(2) = m%FxA * p%GFScaling(2,1) + m%FyA * p%GFScaling(2,2) - m%tau_A * p%GFScaling(2,3) + m%GF(3) = m%FxA * p%GFScaling(3,1) + m%FyA * p%GFScaling(3,2) - m%tau_A * p%GFScaling(3,3) + +end subroutine AeroKinetics +!---------------------------------------------------------------------------------------------------- + +!> Set LinDyn inputs (scaled aerodynamic forces at point A) +subroutine setLDinputs(U0, LD_x, UA_y, p, m, LD_u) + real(ReKi) , intent(in ) :: U0(2) !< Parameters + type(LD_ContinuousStateType), intent(in ) :: LD_x !< LinDyn states + type(UA_OutputType), intent(in ) :: UA_y !< UA outputs + type(Dvr_Parameters), intent(in ) :: p !< Parameters + type(Dvr_Misc), intent(inout) :: m !< Misc aero var + type(LD_InputType), intent(inout) :: LD_u !< LinDyn inputs + + call AeroKinetics (U0, LD_x%q(1:3), LD_x%q(4:6), (/UA_y%Cl, UA_y%Cd, UA_y%Cm/), p, m) + LD_u%Fext(1) = m%GF(1) + LD_u%Fext(2) = m%GF(2) + LD_u%Fext(3) = m%GF(3) + +end subroutine setLDinputs + +!---------------------------------------------------------------------------------------------------- +!> Set UA Inputs from Flow and LinDyn +subroutine setUAinputs(U0, LD_x, p, m, UA_u) + real(ReKi) , intent(in ) :: U0(2) !< Parameters + type(LD_ContinuousStateType), intent(in ) :: LD_x !< LinDyn states + type(Dvr_Parameters), intent(in ) :: p !< Parameters + type(Dvr_Misc), intent(inout) :: m !< Misc aero var + type(UA_InputType), intent(inout) :: UA_u !< UA inputs + + call AeroKinematics(U0, LD_x%q(1:3), LD_x%q(4:6), p, m) + UA_u%UserProp = 0 + UA_u%Re = m%Re + UA_u%omega = -LD_x%q(6) ! NOTE: theta convention for the driver is negative along z, but UA expect an omega along z + ! Angle of attack and relative velocity at 1/4 point/aerodynamic center point "Q" + UA_u%alpha = m%alpha_Q + UA_u%U = sqrt(m%Vrel_norm2_Q) + UA_u%v_ac(1) = UA_u%U * sin(UA_u%alpha) ! In airfoil coordinate system (a) + UA_u%v_ac(2) = UA_u%U * cos(UA_u%alpha) ! In airfoil coordinate system (a) +end subroutine setUAinputs + +!---------------------------------------------------------------------------------------------------- +!> Set UA inptus for a simulation where the angle of attack is prescribed and the relative velocity is constant +subroutine setUAinputsAlphaSim(n, u, t, p, m, errStat, errMsg) + integer, intent(in) :: n + type(UA_InputType), intent(inout) :: u ! System inputs + real(DbKi), intent( out) :: t + type(Dvr_Parameters), intent(in) :: p ! Initialization data for the driver program + type(Dvr_Misc ), intent(inout) :: m ! Initialization data for the driver program + integer, intent(out) :: errStat + character(len=*), intent(out) :: errMsg + integer :: indx + real(ReKi) :: phase + real(ReKi) :: d_ref2AC + real(ReKi) :: alpha_ref + real(ReKi) :: U_ref + real(ReKi) :: v_ref(2) + real(ReKi) :: v_34(2) + logical, parameter :: OscillationAtMidChord=.true. ! for legacy, use false + logical, parameter :: VelocityAt34 =.true. ! for legacy, use false + + ! Initialize error handling variables + ErrMsg = '' + ErrStat = ErrID_None + + u%UserProp = 0 + t = (n-1)*p%dt + + if ( p%SimMod == 1 ) then + if (OscillationAtMidChord) then + d_ref2AC = -0.25_ReKi ! -0.25: oscillations at mid_chord + d_ref2AC = -p%d_34_to_ac/2. ! TODO else - Prefix='Cl_' - sFullyAtt='Dummy' + d_ref2AC = 0.0_ReKi ! 0: oscillations at AC endif - if (UseCm) then - sCm='Cm' + U_ref = p%InflowVel ! m/s + + phase = (n+p%Phase-1)*2*pi/p%StepsPerCycle + alpha_ref = (p%Amplitude * sin(phase) + p%Mean)*D2R ! This needs to be in radians + v_ref(1) = sin(alpha_ref)*U_ref + v_ref(2) = cos(alpha_ref)*U_ref + u%omega = p%Amplitude * cos(phase) * 2*pi/p%StepsPerCycle / p%dt * D2R ! This needs to be in radians derivative: d_alpha /d_t + + u%v_ac(1) = v_ref(1) + u%omega * d_ref2AC* p%Chord + u%v_ac(2) = v_ref(2) + + v_34(1) = u%v_ac(1) + u%omega * 0.5* p%Chord + v_34(2) = u%v_ac(2) + + u%alpha = atan2(u%v_ac(1), u%v_ac(2) ) ! + if (VelocityAt34) then + u%U = sqrt(v_34(1)**2 + v_34(2)**2) ! Using U at 3/4 else - sCm='Cm_Dummy' + u%U = sqrt(u%v_ac(1)**2 + u%v_ac(2)**2) ! Using U at 1/4 endif + u%Re = p%Re ! Option for constant Reynolds or not? + else + ! Interpolate at current time + call interpTimeValue(p%vPrescrAero, t, m%iPALast, m%uPA) + u%alpha = m%uPA(1) ! rad + u%U = m%uPA(2) + u%omega = m%uPA(3) + u%v_ac(1) = sin(u%alpha)*u%U + u%v_ac(2) = cos(u%alpha)*u%U + u%Re = u%U * p%chord / p%KinVisc + end if - ! Loop on tables, write a different file for each table. - do iTab = 1, size(AFI_Params%Table) - tab => AFI_Params%Table(iTab) +end subroutine setUAinputsAlphaSim - ! Compute derived parameters from cl and cd, and UA_BL - if(allocated(cl_smooth)) deallocate(cl_smooth) - if(allocated(cn_smooth)) deallocate(cn_smooth) - if(allocated(cn )) deallocate(cn ) - if(allocated(cl_lin )) deallocate(cl_lin ) - if(allocated(cn_lin )) deallocate(cn_lin ) - allocate(cl_smooth(tab%NumAlf)) - allocate(cn_smooth(tab%NumAlf)) - allocate(cn (tab%NumAlf)) - allocate(cl_lin (tab%NumAlf)) - allocate(cn_lin (tab%NumAlf)) +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Dvr_EndSim(dvr, errStat, errMsg) + type(Dvr_Data), target, intent(inout) :: dvr ! driver data + integer(IntKi) , intent(out) :: errStat ! Status of error message + character(*) , intent(out) :: errMsg ! Error message if errStat /= ErrID_None + character(ErrMsgLen) :: errMsg2 ! temporary Error message if errStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'Dvr_EndSim' + type(Dvr_Outputs), pointer :: out ! driver output, data + out => dvr%out + errStat = ErrID_None + errMsg = '' + ! Close the output file + if (out%fileFmt==idFmt_Both .or. out%fileFmt == idFmt_Ascii) then + if (out%unOutFile > 0) close(out%unOutFile) + endif + if (out%fileFmt==idFmt_Both .or. out%fileFmt == idFmt_Binary) then + call WrScr(' Writing output file: '//trim(out%Root)//'.outb') + call WrBinFAST(trim(out%Root)//'.outb', FileFmtID_ChanLen_In, 'AeroDynDriver', out%WriteOutputHdr, out%WriteOutputUnt, (/0.0_DbKi, dvr%p%dt/), out%storage(:,:), errStat2, errMsg2) + call SetErrStat(errStat2, errMsg2, errStat, errMsg, RoutineName) + endif +end subroutine Dvr_EndSim - - cn = tab%Coefs(:,AFI_Params%ColCl) * cos(tab%alpha) + (tab%Coefs(:,AFI_Params%ColCd) - tab%UA_BL%Cd0) * sin(tab%alpha); - cn_lin = tab%UA_BL%C_nalpha * (tab%alpha - tab%UA_BL%alpha0) - cl_lin = tab%UA_BL%C_lalpha * (tab%alpha - tab%UA_BL%alpha0) - - do iRow = 1, tab%NumAlf - if ((tab%alpha(iRow)tab%UA_BL%alphaUpperWrap) then - cl_lin(iRow) =0.0_ReKi - cn_lin(iRow) =0.0_ReKi - endif - enddo - - ! Smoothing (used priot to compute slope in CalculateUACoeffs) - call kernelSmoothing(tab%alpha, cn , kernelType_TRIWEIGHT, 2.0_ReKi*D2R, cn_smooth) - call kernelSmoothing(tab%alpha, tab%Coefs(:,AFI_Params%ColCl), kernelType_TRIWEIGHT, 2.0_ReKi*D2R, cl_smooth) - - ! Write to file - - CALL GetNewUnit( unOutFile, ErrStat, ErrMsg ) - IF ( ErrStat /= ErrID_None ) RETURN - - CALL OpenFOutFile ( unOutFile, trim(OutRootName)//'.UA.Coefs.'//trim(num2lstr(iTab))//'.out', ErrStat, ErrMsg ) - if (ErrStat >= AbortErrLev) then - call WrScr(Trim(ErrMsg)) - return - end if - - WRITE (unOutFile,'(/,A/)') 'These predictions were generated by UnsteadyAero Driver on '//CurDate()//' at '//CurTime()//'.' - WRITE (unOutFile,'(/,A/)') ' ' - - WRITE(unOutFile, '(20(A20,1x))') 'Alpha', 'Cl', 'Cd', sCm, 'Cn', 'f_st', Prefix//'FullySep', sFullyAtt , 'Cl_lin','Cn_lin','Cl_smooth', 'Cn_smooth' - WRITE(unOutFile, '(20(A20,1x))') '(deg)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)' , '(-)' , '(-)' , '(-)' , '(-)' ,'(-)' - - ! TODO, we could do something with ColCpmim and ColUAf - if (UseCm) then - iStartUA = 4 - do iRow=1,size(tab%Alpha) - WRITE(unOutFile, '(20(F20.6,1x))') tab%Alpha(iRow)*R2D, tab%Coefs(iRow,AFI_Params%ColCl), tab%Coefs(iRow,AFI_Params%ColCd), tab%Coefs(iRow,AFI_Params%ColCm), & - cn(iRow), tab%Coefs(iRow,iStartUA:), cl_lin(iRow), cn_lin(iRow), cl_smooth(iRow), cn_smooth(iRow) - end do - else - iStartUA = 3 - do iRow=1,size(tab%Alpha) - WRITE(unOutFile, '(20(F20.6,1x))') tab%Alpha(iRow)*R2D, tab%Coefs(iRow,AFI_Params%ColCl), tab%Coefs(iRow,AFI_Params%ColCd), 0.0_ReKi, & - cn(iRow), tab%Coefs(iRow,iStartUA:), cl_lin(iRow), cn_lin(iRow), cl_smooth(iRow), cn_smooth(iRow) - end do + + + + +! -------------------------------------------------------------------------------- +! --- IO +! -------------------------------------------------------------------------------- +!---------------------------------------------------------------------------------------------------------------------------------- +!> Concatenate new output channels info to the extisting ones in the driver +!! TODO COPY PASTED FROM AeroDyn_Inflow. Should be placed in NWTC_Lib NWTC_Str +subroutine concatOutputHeaders(WriteOutputHdr0, WriteOutputUnt0, WriteOutputHdr, WriteOutputUnt, errStat, errMsg) + character(ChanLen), dimension(:), allocatable, intent(inout) :: WriteOutputHdr0 !< Channel headers + character(ChanLen), dimension(:), allocatable, intent(inout) :: WriteOutputUnt0 !< Channel units + character(ChanLen), dimension(:), allocatable, intent(inout) :: WriteOutputHdr !< Channel headers + character(ChanLen), dimension(:), allocatable, intent(inout) :: WriteOutputUnt !< Channel units + integer(IntKi) , intent( out) :: errStat !< Status of error message + character(*) , intent( out) :: errMsg !< Error message if errStat /= ErrID_None + ! Locals + character(ChanLen), allocatable :: TmpHdr(:) + character(ChanLen), allocatable :: TmpUnt(:) + integer :: nOld, nAdd + errStat = ErrID_None + errMsg = '' + if (.not.allocated(WriteOutputHdr)) return + if (.not.allocated(WriteOutputHdr0)) then + call move_alloc(WriteOutputHdr, WriteOutputHdr0) + call move_alloc(WriteOutputUnt, WriteOutputUnt0) + else + nOld = size(WriteOutputHdr0) + nAdd = size(WriteOutputHdr) + + call move_alloc(WriteOutputHdr0, TmpHdr) + call move_alloc(WriteOutputUnt0, TmpUnt) + + allocate(WriteOutputHdr0(nOld+nAdd)) + allocate(WriteOutputUnt0(nOld+nAdd)) + WriteOutputHdr0(1:nOld) = TmpHdr + WriteOutputUnt0(1:nOld) = TmpUnt + WriteOutputHdr0(nOld+1:nOld+nAdd) = WriteOutputHdr + WriteOutputUnt0(nOld+1:nOld+nAdd) = WriteOutputUnt + deallocate(TmpHdr) + deallocate(TmpUnt) + endif +end subroutine concatOutputHeaders +!---------------------------------------------------------------------------------------------------------------------------------- +!> Initialize outputs to file for driver +subroutine Dvr_InitializeOutputs(out, numSteps, errStat, errMsg) + type(Dvr_Outputs), intent(inout) :: out + integer(IntKi) , intent(in ) :: numSteps ! Number of time steps + integer(IntKi) , intent( out) :: errStat ! Status of error message + character(*) , intent( out) :: errMsg ! Error message if errStat /= ErrID_None + ! locals + integer(IntKi) :: numOuts +! integer(IntKi) :: i +! integer(IntKi) :: numSpaces +! integer(IntKi) :: iWT +! character(ChanLen) :: colTxt +! character(ChanLen) :: caseTxt +! + numOuts = size(out%WriteOutputHdr) + + call AllocAry(out%outLine, numOuts-1, 'outLine', errStat, errMsg); ! NOTE: time not stored + out%outLine=0.0_ReKi +! +! ! --- Ascii +! if (out%fileFmt==idFmt_Both .or. out%fileFmt == idFmt_Ascii) then +! +! ! compute the width of the column output +! numSpaces = out%ActualChanLen ! the size of column produced by OutFmt +! out%ActualChanLen = max( out%ActualChanLen, MinChanLen ) ! set this to at least MinChanLen , or the size of the column produced by OutFmt +! do i=1,numOuts +! out%ActualChanLen = max(out%ActualChanLen, LEN_TRIM(out%WriteOutputHdr(i))) +! out%ActualChanLen = max(out%ActualChanLen, LEN_TRIM(out%WriteOutputUnt(i))) +! end do +! +! ! create format statements for time and the array outputs: +! out%Fmt_t = '(F'//trim(num2lstr(out%ActualChanLen))//'.4)' +! out%Fmt_a = '"'//out%delim//'"'//trim(out%outFmt) ! format for array elements from individual modules +! numSpaces = out%ActualChanLen - numSpaces ! the difference between the size of the headers and what is produced by OutFmt +! if (numSpaces > 0) then +! out%Fmt_a = trim(out%Fmt_a)//','//trim(num2lstr(numSpaces))//'x' +! end if +! +! ! --- Start writing to ascii input file +! do iWT=1,nWT +! if (nWT>1) then +! sWT = '.T'//trim(num2lstr(iWT)) +! else +! sWT = '' +! endif +! call GetNewUnit(out%unOutFile(iWT), errStat, errMsg) +! if ( errStat >= AbortErrLev ) then +! out%unOutFile(iWT) = -1 +! return +! end if +! call OpenFOutFile ( out%unOutFile(iWT), trim(out%Root)//trim(sWT)//'.out', errStat, errMsg ) +! if ( errStat >= AbortErrLev ) return +! write (out%unOutFile(iWT),'(/,A)') 'Predictions were generated on '//CurDate()//' at '//CurTime()//' using '//trim( version%Name ) +! write (out%unOutFile(iWT),'(1X,A)') trim(GetNVD(out%AD_ver)) +! write (out%unOutFile(iWT),'()' ) !print a blank line +! write (out%unOutFile(iWT),'()' ) !print a blank line +! write (out%unOutFile(iWT),'()' ) !print a blank line +! +! ! Write the names of the output parameters on one line: +! do i=1,numOuts +! call WrFileNR ( out%unOutFile(iWT), out%delim//out%WriteOutputHdr(i)(1:out%ActualChanLen) ) +! end do ! i +! write (out%unOutFile(iWT),'()') +! +! ! Write the units of the output parameters on one line: +! do i=1,numOuts +! call WrFileNR ( out%unOutFile(iWT), out%delim//out%WriteOutputUnt(i)(1:out%ActualChanLen) ) +! end do ! i +! write (out%unOutFile(iWT),'()') +! enddo +! endif +! + ! --- Binary + if (out%fileFmt==idFmt_Both .or. out%fileFmt == idFmt_Binary) then + call AllocAry(out%storage, numOuts-1, numSteps, 'storage', errStat, errMsg) + out%storage= myNaN !0.0_ReKi ! Alternative: myNaN + endif +end subroutine Dvr_InitializeOutputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> Initialize driver (not module-level) output channels +subroutine Dvr_InitializeDriverOutputs(dvr, out, errStat, errMsg) + type(Dvr_Data), intent(inout) :: dvr ! driver data + type(Dvr_Outputs), intent(inout) :: out ! driver output data + integer(IntKi) , intent( out) :: errStat ! Status of error message + character(*) , intent( out) :: errMsg ! Error message if errStat /= ErrID_None + integer(IntKi) :: errStat2 ! Status of error message + character(ErrMsgLen) :: errMsg2 ! Error message + integer :: j + errStat = ErrID_None + errMsg = '' + + out%ny_UA = size(dvr%UA_InitOutData%WriteOutputHdr) + if (dvr%p%SimMod==3) then + out%ny_dvr = 27 ! Driver only ! TODO + out%ny_LD = size(dvr%LD_InitOutData%WriteOutputHdr) + else + out%ny_dvr = 0 + out%ny_LD = 0 + endif + + + ! --- Allocate driver-level outputs + call AllocAry(out%WriteOutputHdr, 1+out%ny_dvr, 'WriteOutputHdr', errStat2, errMsg2); if(Failed()) return + call AllocAry(out%WriteOutputUnt, 1+out%ny_dvr, 'WriteOutputUnt', errStat2, errMsg2); if(Failed()) return + + j=1 + out%WriteOutputHdr(j) = 'Time' ; out%WriteOutputUnt(j) = '(s)' ; j=j+1 + if (dvr%p%SimMod==3) then + ! TODO SIMMOD HARMONIZATION + ! Driver Variables + out%WriteOutputHdr(j) = 'VUndx' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'VUndy' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'VSTx_Q' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'VSTy_Q' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'VSTx_T' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'VSTy_T' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'Vrelx_Q' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'Vrely_Q' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'Vrelx_T' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'Vrely_T' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'Vrel_Q' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'Vrel_T' ; out%WriteOutputUnt(j) = '(m/s)' ; j=j+1 + out%WriteOutputHdr(j) = 'alpha_Q' ; out%WriteOutputUnt(j) = '(deg)' ; j=j+1 + out%WriteOutputHdr(j) = 'alpha_T' ; out%WriteOutputUnt(j) = '(deg)' ; j=j+1 + out%WriteOutputHdr(j) = 'phi_Q' ; out%WriteOutputUnt(j) = '(deg)' ; j=j+1 + out%WriteOutputHdr(j) = 'phi_T' ; out%WriteOutputUnt(j) = '(deg)' ; j=j+1 + out%WriteOutputHdr(j) = 'twist_full' ; out%WriteOutputUnt(j) = '(deg)' ; j=j+1 + out%WriteOutputHdr(j) = 'Re_T' ; out%WriteOutputUnt(j) = '(-)' ; j=j+1 + out%WriteOutputHdr(j) = 'L' ; out%WriteOutputUnt(j) = '(N/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'D' ; out%WriteOutputUnt(j) = '(N/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'M' ; out%WriteOutputUnt(j) = '(Nm/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'Fx_A' ; out%WriteOutputUnt(j) = '(N/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'Fy_A' ; out%WriteOutputUnt(j) = '(N/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'M_A' ; out%WriteOutputUnt(j) = '(Nm/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'GFx' ; out%WriteOutputUnt(j) = '(N/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'GFy' ; out%WriteOutputUnt(j) = '(N/m)' ; j=j+1 + out%WriteOutputHdr(j) = 'GFM' ; out%WriteOutputUnt(j) = '(Nm/m)' ; j=j+1 + ! Dynamics + call concatOutputHeaders(out%WriteOutputHdr, out%WriteOutputUnt, dvr%LD_InitOutData%WriteOutputHdr, dvr%LD_InitOutData%WriteOutputUnt, errStat2, errMsg2) + endif + ! UA + call concatOutputHeaders(out%WriteOutputHdr, out%WriteOutputUnt, dvr%UA_InitOutData%WriteOutputHdr, dvr%UA_InitOutData%WriteOutputUnt, errStat2, errMsg2) + + out%ny = size(out%WriteOutputHdr) + ! Debug Write + !do j = 1, out%ny + ! print*,'Write Out: ',j, trim(out%WriteOutputHdr(j)), ' ', trim(out%WriteOutputUnt(j)) + !enddo +contains + logical function Failed() + CALL SetErrStat(errStat2, errMsg2, errStat, errMsg, 'Dvr_InitializeDriverOutputs' ) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine Dvr_InitializeDriverOutputs +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine Dvr_WriteOutputs(nt, t, dvr, out, errStat, errMsg) + integer(IntKi) , intent(in ) :: nt ! simulation time step + real(DbKi) , intent(in ) :: t ! simulation time (s) + type(Dvr_Data), intent(inout) :: dvr ! driver data + type(Dvr_Outputs) , intent(inout) :: out ! driver uotput options + integer(IntKi) , intent(inout) :: errStat ! Status of error message + character(*) , intent(inout) :: errMsg ! Error message if errStat /= ErrID_None +! ! Local variables. +! character(ChanLen) :: tmpStr ! temporary string to print the time output as text + integer :: nDV , nUA, nLD,j + errStat = ErrID_None + errMsg = '' + out%outLine = myNaN ! Safety +! + ! --- Packing all outputs except time into one array + nDV = out%ny_dvr + nLD = out%ny_LD + nUA = out%ny_UA + ! Driver outputs + j = 1 + if (dvr%p%SimMod==3) then + ! TODO harmonization + out%outLine(j) = dvr%U0(1, 1) ; j=j+1 ! Ux + out%outLine(j) = dvr%U0(1, 2) ; j=j+1 ! Uy + out%outLine(j) = dvr%m%Vst_Q(1) ; j=j+1 ! VSTx_Q + out%outLine(j) = dvr%m%Vst_Q(2) ; j=j+1 ! VSTy_Q + out%outLine(j) = dvr%m%Vst_T(1) ; j=j+1 ! VSTx_T + out%outLine(j) = dvr%m%Vst_T(2) ; j=j+1 ! VSTy_T + out%outLine(j) = dvr%m%Vrel_Q(1) ; j=j+1 ! Vrelx_Q + out%outLine(j) = dvr%m%Vrel_Q(2) ; j=j+1 ! Vrely_Q + out%outLine(j) = dvr%m%Vrel_T(1) ; j=j+1 ! Vrelx_T + out%outLine(j) = dvr%m%Vrel_T(2) ; j=j+1 ! Vrely_T + out%outLine(j) = sqrt(dvr%m%Vrel_norm2_Q) ; j=j+1 ! Vrel_Q + out%outLine(j) = sqrt(dvr%m%Vrel_norm2_T) ; j=j+1 ! Vrel_T + out%outLine(j) = dvr%m%alpha_Q*R2D ; j=j+1 ! alpha_Q + out%outLine(j) = dvr%m%alpha_T*R2D ; j=j+1 ! alpha_T + out%outLine(j) = dvr%m%phi_Q *R2D ; j=j+1 ! phi_Q + out%outLine(j) = dvr%m%phi_T *R2D ; j=j+1 ! phi_T + out%outLine(j) = dvr%m%twist_full*R2D ; j=j+1 ! twist_full + out%outLine(j) = dvr%m%Re ; j=j+1 ! Re_T + out%outLine(j) = dvr%m%L ; j=j+1 ! L + out%outLine(j) = dvr%m%D ; j=j+1 ! D + out%outLine(j) = dvr%m%tau_Q ; j=j+1 ! M + out%outLine(j) = dvr%m%FxA ; j=j+1 ! Fx_A + out%outLine(j) = dvr%m%FyA ; j=j+1 ! Fy_A + out%outLine(j) = dvr%m%tau_A ; j=j+1 ! M_A + out%outLine(j) = dvr%m%GF(1) ; j=j+1 ! GFx + out%outLine(j) = dvr%m%GF(2) ; j=j+1 ! GFy + out%outLine(j) = dvr%m%GF(3) ; j=j+1 ! GFM + ! LD Outputs + out%outLine(nDV+1:nDV+nLD) = dvr%LD_y%WriteOutput(1:nLD) + endif + ! UA Outputs + out%outLine(nDV+nLD+1:nDV+nLD+nUA) = dvr%UA_y%WriteOutput(1:nUA) + + !if (out%fileFmt==idFmt_Both .or. out%fileFmt == idFmt_Ascii) then + ! ! ASCII + ! ! time + ! write( tmpStr, out%Fmt_t ) t ! '(F15.4)' + ! call WrFileNR( out%unOutFile, tmpStr(1:out%ActualChanLen) ) + ! call WrNumAryFileNR(out%unOutFile, out%outLine, out%Fmt_a, errStat, errMsg) + ! ! write a new line (advance to the next line) + ! write(out%unOutFile,'()') + !endif + if (out%fileFmt==idFmt_Both .or. out%fileFmt == idFmt_Binary) then + ! Store for binary + out%storage(:, nt) = out%outLine(:) + !out%storage(1:nDV+nAD+nIW, nt) = out%outLine(1:nDV+nAD+nIW) + endif +end subroutine Dvr_WriteOutputs +! + + +subroutine WriteAFITables(AFI_Params, OutRootName, UseCm, UA_f_cn) + + type(AFI_ParameterType), intent(in), target :: AFI_Params + character(len=*) , intent(in) :: OutRootName + logical , intent(in) :: UseCm + logical , intent(in) :: UA_f_cn + + integer(IntKi) :: unOutFile + integer(IntKi) :: ErrStat + character(ErrMsgLen) :: ErrMsg + + Real(ReKi), allocatable :: cl_smooth(:) + Real(ReKi), allocatable :: cn_smooth(:) + Real(ReKi), allocatable :: cn(:) + Real(ReKi), allocatable :: cl_lin(:) + Real(ReKi), allocatable :: cn_lin(:) + character(len=3) :: Prefix + character(len=11) :: sFullyAtt + character(len=8) :: sCm + integer :: iTab, iRow, iStartUA + type(AFI_Table_Type), pointer :: tab !< Alias + + if (UA_f_cn) then + Prefix='Cn_' + sFullyAtt='Cn_FullyAtt' + else + Prefix='Cl_' + sFullyAtt='Dummy' + endif + if (UseCm) then + sCm='Cm' + else + sCm='Cm_Dummy' + endif + + + ! Loop on tables, write a different file for each table. + do iTab = 1, size(AFI_Params%Table) + tab => AFI_Params%Table(iTab) + + ! Compute derived parameters from cl and cd, and UA_BL + if(allocated(cl_smooth)) deallocate(cl_smooth) + if(allocated(cn_smooth)) deallocate(cn_smooth) + if(allocated(cn )) deallocate(cn ) + if(allocated(cl_lin )) deallocate(cl_lin ) + if(allocated(cn_lin )) deallocate(cn_lin ) + allocate(cl_smooth(tab%NumAlf)) + allocate(cn_smooth(tab%NumAlf)) + allocate(cn (tab%NumAlf)) + allocate(cl_lin (tab%NumAlf)) + allocate(cn_lin (tab%NumAlf)) + + + cn = tab%Coefs(:,AFI_Params%ColCl) * cos(tab%alpha) + (tab%Coefs(:,AFI_Params%ColCd) - tab%UA_BL%Cd0) * sin(tab%alpha); + cn_lin = tab%UA_BL%C_nalpha * (tab%alpha - tab%UA_BL%alpha0) + cl_lin = tab%UA_BL%C_lalpha * (tab%alpha - tab%UA_BL%alpha0) + + do iRow = 1, tab%NumAlf + if ((tab%alpha(iRow)tab%UA_BL%alphaUpperWrap) then + cl_lin(iRow) =0.0_ReKi + cn_lin(iRow) =0.0_ReKi endif - - CLOSE(unOutFile) enddo + + ! Smoothing (used priot to compute slope in CalculateUACoeffs) + call kernelSmoothing(tab%alpha, cn , kernelType_TRIWEIGHT, 2.0_ReKi*D2R, cn_smooth) + call kernelSmoothing(tab%alpha, tab%Coefs(:,AFI_Params%ColCl), kernelType_TRIWEIGHT, 2.0_ReKi*D2R, cl_smooth) + + ! Write to file + + CALL GetNewUnit( unOutFile, ErrStat, ErrMsg ) + IF ( ErrStat /= ErrID_None ) RETURN + + CALL OpenFOutFile ( unOutFile, trim(OutRootName)//'.Coefs.'//trim(num2lstr(iTab))//'.out', ErrStat, ErrMsg ) + if (ErrStat >= AbortErrLev) then + call WrScr(Trim(ErrMsg)) + return + end if + + WRITE (unOutFile,'(/,A/)') 'These predictions were generated by UnsteadyAero Driver on '//CurDate()//' at '//CurTime()//'.' + WRITE (unOutFile,'(/,A/)') ' ' + + WRITE(unOutFile, '(20(A20,1x))') 'Alpha', 'Cl', 'Cd', sCm, 'Cn', 'f_st', Prefix//'FullySep', sFullyAtt , 'Cl_lin','Cn_lin','Cl_smooth', 'Cn_smooth' + WRITE(unOutFile, '(20(A20,1x))') '(deg)', '(-)', '(-)', '(-)', '(-)', '(-)', '(-)' , '(-)' , '(-)' , '(-)' , '(-)' ,'(-)' + + ! TODO, we could do something with ColCpmim and ColUAf + if (UseCm) then + iStartUA = 4 + do iRow=1,size(tab%Alpha) + WRITE(unOutFile, '(20(F20.6,1x))') tab%Alpha(iRow)*R2D, tab%Coefs(iRow,AFI_Params%ColCl), tab%Coefs(iRow,AFI_Params%ColCd), tab%Coefs(iRow,AFI_Params%ColCm), & + cn(iRow), tab%Coefs(iRow,iStartUA:), cl_lin(iRow), cn_lin(iRow), cl_smooth(iRow), cn_smooth(iRow) + end do + else + iStartUA = 3 + do iRow=1,size(tab%Alpha) + WRITE(unOutFile, '(20(F20.6,1x))') tab%Alpha(iRow)*R2D, tab%Coefs(iRow,AFI_Params%ColCl), tab%Coefs(iRow,AFI_Params%ColCd), 0.0_ReKi, & + cn(iRow), tab%Coefs(iRow,iStartUA:), cl_lin(iRow), cn_lin(iRow), cl_smooth(iRow), cn_smooth(iRow) + end do + endif - end subroutine WriteAFITables + CLOSE(unOutFile) + enddo + +end subroutine WriteAFITables end module UA_Dvr_Subs diff --git a/modules/aerodyn/src/UnsteadyAero.f90 b/modules/aerodyn/src/UnsteadyAero.f90 index 268757ecd9..ffb217631c 100644 --- a/modules/aerodyn/src/UnsteadyAero.f90 +++ b/modules/aerodyn/src/UnsteadyAero.f90 @@ -522,7 +522,7 @@ subroutine ComputeKelvinChain( i, j, u, p, xd, OtherState, misc, AFInfo, KC, BL_ KC%Cn_q_circ = KC%C_nalpha_circ*KC%q_f_cur/2.0 - KC%X3 - KC%X4 ! Eqn 1.16 - else ! these aren't used (they are possibly output to UA output file (when UA_OUTS defined) file, though) + else ! these aren't used (they are possibly output to UA output file when UA_OUTS is > 0 file, though) KC%X3 = 0.0_ReKi KC%X4 = 0.0_ReKi KC%Cn_q_circ = 0.0_ReKi @@ -740,12 +740,14 @@ subroutine UA_SetParameters( dt, InitInp, p, AFInfo, AFIndx, ErrStat, ErrMsg ) if (ErrStat >= AbortErrLev) return p%c = InitInp%c ! this can't be 0 + p%d_34_to_ac = InitInp%d_34_to_ac ! In the future, set this for all nodes! p%numBlades = InitInp%numBlades p%nNodesPerBlade = InitInp%nNodesPerBlade p%UAMod = InitInp%UAMod p%a_s = InitInp%a_s ! this can't be 0 p%Flookup = InitInp%Flookup p%ShedEffect = InitInp%ShedEffect + p%UA_OUTS = InitInp%UA_OUTS if (p%UAMod==UA_HGM .or. p%UAMod==UA_HGMV) then UA_NumLinStates = 4 @@ -755,6 +757,9 @@ subroutine UA_SetParameters( dt, InitInp, p, AFInfo, AFIndx, ErrStat, ErrMsg ) else if (p%UAMod==UA_OYE) then UA_NumLinStates = 1 p%lin_nx = p%numBlades*p%nNodesPerBlade*UA_NumLinStates ! continuous state per node per blade, but stored at position 4 + else if (p%UAMod==UA_None) then + p%lin_nx = 0 + UA_NumLinStates = 0 else p%lin_nx = 0 UA_NumLinStates = 0 @@ -944,13 +949,12 @@ subroutine UA_InitStates_Misc( p, x, xd, OtherState, m, ErrStat, ErrMsg ) call AllocAry(OtherState%sigma1m ,p%nNodesPerBlade,p%numBlades,'OtherState%sigma1m',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) call AllocAry(OtherState%sigma3 ,p%nNodesPerBlade,p%numBlades,'OtherState%sigma3',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) - -# ifdef UA_OUTS + if(p%UA_OUTS>0) then call AllocAry(m%TESF ,p%nNodesPerBlade,p%numBlades,'m%TESF',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) call AllocAry(m%LESF ,p%nNodesPerBlade,p%numBlades,'m%LESF',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) call AllocAry(m%VRTX ,p%nNodesPerBlade,p%numBlades,'m%VRTX',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) call AllocAry(m%T_Sh ,p%nNodesPerBlade,p%numBlades,'m%T_Sh',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) -# endif + endif end if call AllocAry(m%weight ,p%nNodesPerBlade,p%numBlades,'m%weight',ErrStat2,ErrMsg2); call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) @@ -1041,12 +1045,12 @@ subroutine UA_ReInit( p, x, xd, OtherState, m, ErrStat, ErrMsg ) OtherState%sigma1m = 1.0_ReKi OtherState%sigma3 = 1.0_ReKi -# ifdef UA_OUTS + if (p%UA_OUTS>0) then m%TESF = .FALSE. m%LESF = .FALSE. m%VRTX = .FALSE. m%T_sh = 0.0_ReKi -# endif + endif xd%Cn_prime_minus1 = 0.0_ReKi xd%alpha_minus1 = 0.0_ReKi @@ -1120,12 +1124,6 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & integer(IntKi) :: errStat2 ! temporary Error status of the operation character(*), parameter :: RoutineName = 'UA_Init' -#ifdef UA_OUTS - CHARACTER(6) :: TmpChar ! Temporary char array to hold the node digits (3 places only!!!!) - integer(IntKi) :: i,j, iNode, iOffset - character(64) :: chanPrefix -#endif - ! Initialize variables for this routine ErrStat = ErrID_None ErrMsg = "" @@ -1135,30 +1133,55 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & call NWTC_Init( EchoLibVer=.FALSE. ) if (InitInp%WrSum) then - call UA_WriteAFIParamsToFile(InitInp, AFInfo, ErrStat2, ErrMsg2) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + call UA_WriteAFIParamsToFile(InitInp, AFInfo, ErrStat2, ErrMsg2); if(Failed()) return end if - call UA_ValidateInput(InitInp, ErrStat2, ErrMsg2) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + call UA_ValidateInput(InitInp, ErrStat2, ErrMsg2); if(Failed()) return ! Allocate and set parameter data structure using initialization data - call UA_SetParameters( interval, InitInp, p, AFInfo, AFIndx, ErrStat2, ErrMsg2 ) - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + call UA_SetParameters( interval, InitInp, p, AFInfo, AFIndx, ErrStat2, ErrMsg2 ); if(Failed()) return - ! initialize the discrete states, other states, and misc variables - call UA_InitStates_Misc( p, x, xd, OtherState, m, ErrStat2, ErrMsg2 ) ! initialize the continuous states - call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - if (ErrStat >= AbortErrLev) return + ! initialize the states, and misc variables + call UA_InitStates_Misc( p, x, xd, OtherState, m, ErrStat2, ErrMsg2 ); if(Failed()) return + ! --- Write Outputs + call UA_Init_Outputs(InitInp, p, y, InitOut, errStat2, errMsg2); if(Failed()) return -#ifdef UA_OUTS +contains + logical function Failed() + call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'UA_Init' ) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine UA_Init + +!============================================================================== +subroutine UA_Init_Outputs(InitInp, p, y, InitOut, errStat, errMsg) + type(UA_InitInputType), intent(in ) :: InitInp ! input data for initialization routine ; we're moving allocated data from InitInp to p so must also be intent(out) + type(UA_ParameterType), intent(inout) :: p ! Parameters + type(UA_OutputType), intent(inout) :: y ! Initial system outputs (outputs are not calculated; + !type(UA_MiscVarType), intent( out) :: m ! Initial misc/optimization variables + type(UA_InitOutputType), intent( out) :: InitOut ! Output for initialization routine + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + character(6) :: TmpChar ! Temporary char array to hold the node digits (3 places only!!!!) + integer(IntKi) :: i,j, iNode, iOffset + character(64) :: chanPrefix + character(ErrMsgLen) :: errMsg2 ! temporary Error message if ErrStat /= ErrID_None + integer(IntKi) :: errStat2 ! temporary Error status of the operation + character(*), parameter :: RoutineName = 'UA_Init' + errStat = errID_None + errMsg = "" + + if (p%UA_OUTS==0) then + p%NumOuts = 0 + p%unOutFile = -1 + return + endif ! Allocate and set the InitOut data - if (p%UAMod == UA_HGM .or. p%UAMod == UA_OYE) then + if (p%UAMod == UA_None) then + p%NumOuts = 11 + elseif (p%UAMod == UA_HGM .or. p%UAMod == UA_OYE) then p%NumOuts = 20 elseif(p%UAMod == UA_HGMV) then p%NumOuts = 21 @@ -1184,8 +1207,12 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & iOffset = (i-1)*p%NumOuts + (j-1)*p%nNodesPerBlade*p%NumOuts !chanPrefix = "B"//trim(num2lstr(j))//"N"//trim(num2lstr(i)) - write (TmpChar,'(I3.3)') i ! 3 digit number - chanPrefix = 'AB' // TRIM(Num2LStr(j)) // 'N' // TRIM(TmpChar) + if ((p%numBlades==1) .and. (p%nNodesPerBlade==1) .and. p%UA_OUTS==1) then + chanPrefix='' ! UA_Driver + else + write (TmpChar,'(I3.3)') i ! 3 digit number + chanPrefix = 'AB' // TRIM(Num2LStr(j)) // 'N' // TRIM(TmpChar) + endif InitOut%WriteOutputHdr(iOffset+ 1) = trim(chanPrefix)//'Alpha' InitOut%WriteOutputHdr(iOffset+ 2) = trim(chanPrefix)//'Vrel' @@ -1203,7 +1230,20 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & InitOut%WriteOutputUnt(iOffset+ 6) ='(-)' InitOut%WriteOutputUnt(iOffset+ 7) ='(-)' - if (p%UAmod == UA_HGM .or. p%UAMod == UA_HGMV .or. p%UAMod == UA_OYE) then + if (p%UAmod == UA_None) then + + InitOut%WriteOutputHdr(iOffset+ 8) = trim(chanPrefix)//'omega' + InitOut%WriteOutputHdr(iOffset+ 9) = trim(chanPrefix)//'alphaE' + InitOut%WriteOutputHdr(iOffset+10) = trim(chanPrefix)//'Tu' + InitOut%WriteOutputHdr(iOffset+11) = trim(chanPrefix)//'alpha_34' + + InitOut%WriteOutputUnt(iOffset+ 8) = '(deg/sec)' + InitOut%WriteOutputUnt(iOffset+ 9) = '(deg)' + InitOut%WriteOutputUnt(iOffset+10) = '(s)' + InitOut%WriteOutputUnt(iOffset+11) = '(deg)' + + + elseif (p%UAmod == UA_HGM .or. p%UAMod == UA_HGMV .or. p%UAMod == UA_OYE) then InitOut%WriteOutputHdr(iOffset+ 8) = trim(chanPrefix)//'omega' InitOut%WriteOutputHdr(iOffset+ 9) = trim(chanPrefix)//'alphaE' @@ -1282,7 +1322,7 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & InitOut%WriteOutputUnt(iOffset+25) = '(m/s)' InitOut%WriteOutputUnt(iOffset+26) = '(m/s)' - else + else if (p%UAmod == UA_Baseline .or. p%UAMod == UA_Gonzalez .or. p%UAMod == UA_MinnemaPierce) then InitOut%WriteOutputHdr(iOffset+ 8) = trim(chanPrefix)//'Cn_aq_circ' InitOut%WriteOutputHdr(iOffset+ 9) = trim(chanPrefix)//'Cn_aq_nc' @@ -1363,6 +1403,8 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & InitOut%WriteOutputUnt(iOffset+44) ='(-)' InitOut%WriteOutputUnt(iOffset+45) ='(deg)' + else + call SetErrStat( ErrID_Fatal, 'Programming error UAmod case not accounted for.', ErrStat, ErrMsg, RoutineName ); return end if end do @@ -1372,11 +1414,13 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & p%OutFmt = 'ES19.5e3' p%Delim ='' - if (p%NumOuts > 0) then + ! --- Write to File + if ((p%NumOuts > 0) .and. p%UA_OUTS==2) then + call WrScr(' UA: Writing separate output file: '//trim((InitInp%OutRootName)//'.out')) CALL GetNewUnit( p%unOutFile, ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return - CALL OpenFOutFile ( p%unOutFile, trim(InitInp%OutRootName)//'.UA.out', ErrStat2, ErrMsg2 ) + CALL OpenFOutFile ( p%unOutFile, trim(InitInp%OutRootName)//'.out', ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return @@ -1396,35 +1440,27 @@ subroutine UA_Init( InitInp, u, p, x, xd, OtherState, y, m, Interval, & WRITE (p%unOutFile,'(:,A,'//trim( p%OutSFmt )//')', ADVANCE='no' ) p%Delim, trim(InitOut%WriteOutputUnt(i)) end do WRITE (p%unOutFile,'()', IOSTAT=ErrStat2) ! write the line return - end if - + else -#else - p%NumOuts = 0 - p%unOutFile = -1 - !..................................... - ! add the following two lines only to avoid compiler warnings about uninitialized variables when not building the UA driver: - y%cm = 0.0_ReKi - InitOut%Version = ProgDesc( 'Unsteady Aero', '', '' ) - !..................................... - -#endif - -end subroutine UA_Init + call WrScr(' UA: saving write outputs') + + end if +end subroutine UA_Init_Outputs !============================================================================== subroutine UA_ValidateInput(InitInp, ErrStat, ErrMsg) type(UA_InitInputType), intent(in ) :: InitInp ! Input data for initialization routine integer(IntKi), intent( out) :: ErrStat ! Error status of the operation character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + integer, parameter :: UA_VALID(7) = (/UA_None, UA_Gonzalez, UA_MinnemaPierce, UA_HGM ,UA_HGMV, UA_Oye, UA_BV/) character(*), parameter :: RoutineName = 'UA_ValidateInput' ErrStat = ErrID_None ErrMsg = "" - if (InitInp%UAMod < UA_Gonzalez .or. InitInp%UAMod > UA_BV ) call SetErrStat( ErrID_Fatal, & - "In this version, UAMod must be 2 (Gonzalez's variant), 3 (Minnema/Pierce variant), 4 (continuous HGM model), 5 (HGM with vortex), & - &6 (Oye), 7 (Boeing-Vertol)", ErrStat, ErrMsg, RoutineName ) ! NOTE: for later- 1 (baseline/original) + if (.not.(any(InitInp%UAMod==UA_VALID))) call SetErrStat( ErrID_Fatal, & + "In this version, UAMod must be 0 (None), 2 (Gonzalez's variant), 3 (Minnema/Pierce variant), 4 (continuous HGM model), 5 (HGM with vortex), & + &6 (Oye), 7 (Boing-Vertol)", ErrStat, ErrMsg, RoutineName ) ! NOTE: for later- 1 (baseline/original) if (.not. InitInp%FLookUp ) call SetErrStat( ErrID_Fatal, 'FLookUp must be TRUE for this version.', ErrStat, ErrMsg, RoutineName ) @@ -1613,8 +1649,10 @@ subroutine UA_TurnOff_param(p, AFInfo, ErrStat, ErrMsg) end if end do + if (p%UAMod == UA_None) then + ! pass - if (p%UAMod == UA_HGM .or. p%UAMod == UA_OYE) then + else if (p%UAMod == UA_HGM .or. p%UAMod == UA_OYE) then ! unsteady aerodynamics will be turned off if Cl,alpha = 0 do j=1, AFInfo%NumTabs if ( EqualRealNos(AFInfo%Table(j)%UA_BL%C_lalpha, 0.0_ReKi) ) then @@ -1698,7 +1736,7 @@ subroutine UA_UpdateDiscOtherState_BV( i, j, u, p, xd, OtherState, AFInfo, m, Er ! --- Filter angle of attack ! Using angle of attack at AC or 3/4 point - alpha_34 = Get_Alpha34(u%v_ac, u%omega, 0.5_ReKi*p%c(i,j)) + alpha_34 = Get_Alpha34(u%v_ac, u%omega, p%d_34_to_ac*p%c(i,j)) ! Angle of attack at previous time if (OtherState%FirstPass(i,j)) then alpha_minus1 = alpha_34 @@ -1767,7 +1805,7 @@ subroutine BV_getAlphas(i, j, u, p, xd, BL_p, tc, alpha_34, alphaE_L, alphaLag_D real(ReKi), parameter :: umach = 0.0_ReKi !< Mach number umach=Urel*Minf, Minf (freestrem Mach) for incompressible ! Angle of attack at 3/4 chord point - alpha_34 = Get_Alpha34(u%v_ac, u%omega, 0.5_ReKi*p%c(i,j)) + alpha_34 = Get_Alpha34(u%v_ac, u%omega, p%d_34_to_ac*p%c(i,j)) ! --- Intermediate variables, using CACTUS notations adotnorm = xd%alpha_dot(i,j) * Get_Tu(u%u, p%c(i,j)) @@ -2218,12 +2256,12 @@ subroutine UA_UpdateDiscOtherState( i, j, u, p, xd, OtherState, AFInfo, m, ErrSt end if end if -#ifdef UA_OUTS + if (p%UA_OUTS>0) then m%TESF(i,j) = TESF m%LESF(i,j) = LESF m%VRTX(i,j) = VRTX m%T_sh(i,j) = T_sh -#endif + endif end subroutine UA_UpdateDiscOtherState @@ -2270,6 +2308,7 @@ subroutine UA_UpdateStates( i, j, t, n, u, uTimes, p, x, xd, OtherState, AFInfo, !BJJ: u%u == 0 seems to be the root cause of all sorts of numerical problems.... + if (p%UAMod == UA_None) return ! we don't have any states to update here if (p%UA_off_forGood(i,j)) return ! we don't have any states to update here @@ -2740,7 +2779,7 @@ SUBROUTINE Get_HGM_constants(i, j, p, u, x, BL_p, Tu, alpha_34, alphaE) Tu = Get_Tu(u%u, p%c(i,j)) if (present(alpha_34)) then - alpha_34 = Get_Alpha34(u%v_ac, u%omega, 0.5_ReKi*p%c(i,j)) + alpha_34 = Get_Alpha34(u%v_ac, u%omega, p%d_34_to_ac*p%c(i,j)) if (present(alphaE)) then ! Variables derived from states @@ -2756,19 +2795,19 @@ SUBROUTINE Get_HGM_constants(i, j, p, u, x, BL_p, Tu, alpha_34, alphaE) END SUBROUTINE Get_HGM_constants !> Compute angle of attack at 3/4 chord point based on values at Aerodynamic center -real(ReKi) function Get_Alpha34(v_ac, omega, d_ac_to_34) - real(ReKi), intent(in) :: v_ac(2) !< Velocity at aerodynamic center +real(ReKi) function Get_Alpha34(v_ac, omega, d_34_to_ac) + real(ReKi), intent(in) :: v_ac(2) !< Velocity at aerodynamic center (AC) real(ReKi), intent(in) :: omega !< pitching rate of airfoil - real(ReKi), intent(in) :: d_ac_to_34 !< distance from aerodynamic center to 3/4 chord point - Get_Alpha34 = atan2(v_ac(1) + omega * d_ac_to_34, v_ac(2) ) ! Uaero - Uelast + real(ReKi), intent(in) :: d_34_to_ac !< distance from 3/4 chord to AC point, assumed >0, e.g. =0.5c + Get_Alpha34 = atan2(v_ac(1) + omega * d_34_to_ac, v_ac(2) ) ! Uaero - Uelast end function Get_Alpha34 !> Compute angle of attack at 2/4 chord point based on values at Aerodynamic center -real(ReKi) function Get_Alpha24(v_ac, omega, d_ac_to_24) - real(ReKi), intent(in) :: v_ac(2) !< Velocity at aerodynamic center +real(ReKi) function Get_Alpha24(v_ac, omega, d_24_to_ac) + real(ReKi), intent(in) :: v_ac(2) !< Velocity at aerodynamic center (AC) real(ReKi), intent(in) :: omega !< pitching rate of airfoil - real(ReKi), intent(in) :: d_ac_to_24 !< distance from aerodynamic center to 2/4 chord point - Get_Alpha24 = atan2(v_ac(1) + omega * d_ac_to_24, v_ac(2) ) ! Uaero - Uelast + real(ReKi), intent(in) :: d_24_to_ac !< distance from 2/4 chord to AC point, assumed >0, e.g. =0.25c + Get_Alpha24 = atan2(v_ac(1) + omega * d_24_to_ac, v_ac(2) ) ! Uaero - Uelast end function Get_Alpha24 !> Compute time constant based on relative velocity u_rel @@ -3315,19 +3354,14 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, real(ReKi) :: alphaE_L, alphaE_D ! effective angle of attack for lift and drag real(ReKi) :: alphaLag_D ! lagged angle of attack for drag calculation real(ReKi) :: adotnorm -#ifdef UA_OUTS real(ReKi) :: delN real(ReKi) :: delP real(ReKi) :: gammaL real(ReKi) :: gammaD real(ReKi) :: TransA -#endif type(AFI_OutputType) :: AFI_interp -#ifdef UA_OUTS - integer :: iOffset -#endif ErrStat = ErrID_None ! no error has occurred ErrMsg = "" @@ -3342,8 +3376,21 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, call UA_fixInputs(u_in, u, ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) k = abs(u%omega * p%c(i, j) / (2.0_ReKi* u%u)) - - if ( p%UA_off_forGood(i,j) .or. (OtherState%FirstPass(i, j) .and. p%UAMod < UA_HGM) ) then ! note: if u%U isn't zero because we've called UA_fixInputs + + if ( p%UAMod == UA_None) then + + ! Compute steady aero using alpha 34 to be consistent with most UA models + Tu = Get_Tu(u%u, p%c(i,j)) + alpha_34 = Get_Alpha34(u%v_ac, u%omega, p%d_34_to_ac*p%c(i,j)) + call AFI_ComputeAirfoilCoefs( alpha_34, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + y%Cl = AFI_interp%Cl + y%Cd = AFI_interp%Cd + y%Cm = AFI_interp%Cm + y%Cn = y%Cl*cos(u%alpha) + y%Cd*sin(u%alpha) + y%Cc = y%Cl*sin(u%alpha) - y%Cd*cos(u%alpha) + if (AFInfo%ColCm == 0) y%Cm = 0.0_ReKi + + else if ( p%UA_off_forGood(i,j) .or. (OtherState%FirstPass(i, j) .and. p%UAMod < UA_HGM) ) then ! note: if u%U isn't zero because we've called UA_fixInputs misc%weight(i,j) = 0.0 @@ -3458,7 +3505,8 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, y%Cn = y%Cl*cos(u%alpha) + y%Cd*sin(u%alpha) y%Cc = y%Cl*sin(u%alpha) - y%Cd*cos(u%alpha) - else + + elseif (p%UAMod == UA_HGMV) then ! limit x5?: x5 = x_in%x(5) @@ -3486,6 +3534,9 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, ! alphaF = x_in%x(3) / BL_p%c_lalpha + BL_p%alpha0 y%Cm = AFI_interp%Cm + cn_circ * delta_c_mf_primeprime - 0.0_ReKi * piBy2 * Tu * u%omega - 0.25_ReKi*(1.0_ReKi - cos(pi * tV_ratio ))*x5 end if + + else + call SetErrStat(ErrID_Fatal, "Programming error, UAMod continuous model not accounted for", ErrStat, ErrMsg, RoutineName) end if @@ -3493,7 +3544,7 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, call UA_BlendSteady(u, p, AFInfo, y, misc%FirstWarn_UA_off, misc%weight(i,j), ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - else + elseif (p%UAMod == UA_Baseline .or. p%UAMod == UA_Gonzalez .or. p%UAMod == UA_MinnemaPierce) then ! --- CalcOutput Beddoes-Leishman type models M = u%U / p%a_s @@ -3641,11 +3692,22 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, call UA_BlendSteady(u, p, AFInfo, y, misc%FirstWarn_UA_off, misc%weight(i,j), ErrStat2, ErrMsg2) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + else + call SetErrStat(ErrID_Fatal, "Programming error, UAMod not accounted for", ErrStat, ErrMsg, RoutineName) + end if ! Switch on UAMod + + if (p%UA_OUTS>0) then + if (allocated(y%WriteOutput)) then !bjj: because BEMT uses local variables for UA output, y%WriteOutput is not necessarially allocated. Need to figure out a better solution. + call CalcWriteOutputs() + endif + endif -#ifdef UA_OUTS - iOffset = (i-1)*p%NumOuts + (j-1)*p%nNodesPerBlade*p%NumOuts - if (allocated(y%WriteOutput)) then !bjj: because BEMT uses local variables for UA output, y%WriteOutput is not necessarially allocated. Need to figure out a better solution. +contains + + subroutine CalcWriteOutputs() + integer :: iOffset + iOffset = (i-1)*p%NumOuts + (j-1)*p%nNodesPerBlade*p%NumOuts y%WriteOutput(iOffset+ 1) = u%alpha*R2D y%WriteOutput(iOffset+ 2) = u%U @@ -3654,8 +3716,14 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, y%WriteOutput(iOffset+ 5) = y%Cl y%WriteOutput(iOffset+ 6) = y%Cd y%WriteOutput(iOffset+ 7) = y%Cm + + if (p%UAMod == UA_None) then + y%WriteOutput(iOffset+ 8) = u%omega*R2D + y%WriteOutput(iOffset+ 9) = alpha_34*R2D + y%WriteOutput(iOffset+10) = Tu + y%WriteOutput(iOffset+11) = alpha_34*R2D - if (p%UAMod == UA_HGM .or. p%UAMod == UA_HGMV .or. p%UAMod == UA_OYE) then + elseif (p%UAMod == UA_HGM .or. p%UAMod == UA_HGMV .or. p%UAMod == UA_OYE) then y%WriteOutput(iOffset+ 8) = u%omega*R2D y%WriteOutput(iOffset+ 9) = alphaE*R2D y%WriteOutput(iOffset+10) = Tu @@ -3752,11 +3820,9 @@ subroutine UA_CalcOutput( i, j, t, u_in, p, x, xd, OtherState, AFInfo, y, misc, y%WriteOutput(iOffset+45) = KC%alpha_filt_cur*R2D end if - end if -#endif + end subroutine CalcWriteOutputs -contains - !> Calc Outputs for Boeing-Vertol dynamic stall + !> Calc Outputs for Boieng-Vertol dynamic stall !! See BV_DynStall.f95 of CACTUS, and [70], notations kept more or less consistent subroutine BV_CalcOutput() real(ReKi) :: alpha_50 @@ -3772,15 +3838,13 @@ subroutine BV_CalcOutput() call BV_getAlphas(i, j, u, p, xd, BL_p, AFInfo%RelThickness, alpha_34, alphaE_L, alphaLag_D, adotnorm) alphaE_D = BV_alphaE_D(adotnorm, alpha_34, alphaLag_D, BL_p, OtherState%activeD(i,j)) -#ifdef UA_OUTS ! --- Recompute variables, for temporary output to file only ! Calculate deltas to negative and positive stall angle (delN, and delP) - call BV_delNP(adotnorm, alpha_34, alphaLag_D, BL_p, OtherState%activeD(i,j), delN, delP) - call BV_getGammas(tc=AFInfo%RelThickness, umach=0.0_ReKi, gammaL=gammaL, gammaD=gammaD) - TransA = BV_TransA(BL_p) -#endif - - + if (p%UA_OUTS>0) then + call BV_delNP(adotnorm, alpha_34, alphaLag_D, BL_p, OtherState%activeD(i,j), delN, delP) + call BV_getGammas(tc=AFInfo%RelThickness, umach=0.0_ReKi, gammaL=gammaL, gammaD=gammaD) + TransA = BV_TransA(BL_p) + endif ! --- Cl, _, at effective angle of attack alphaE if (OtherState%activeL(i,j)) then @@ -3808,7 +3872,7 @@ subroutine BV_CalcOutput() Cm25_stat = AFI_interp%Cm endif ! Static coeffs at 1/2 chord (alpha_50) - alpha_50 = Get_Alpha24(u%v_ac, u%omega, 0.25_ReKi*p%c(i,j)) + alpha_50 = Get_Alpha24(u%v_ac, u%omega, (p%d_34_to_ac-0.25)*p%c(i,j)) ! NOTE: d_24_to_ac = (d_34_to_ac - 1/4) call AFI_ComputeAirfoilCoefs(alpha_50, u%Re, u%UserProp, AFInfo, AFI_interp, ErrStat2, ErrMsg2); call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) Cl50_stat = AFI_interp%Cl ! Static coeffs at 3/4 chord (alpha_34) @@ -3845,8 +3909,7 @@ subroutine UA_WriteOutputToFile(t, p, y) integer :: k ! Generate file outputs -#ifdef UA_OUTS - if (p%unOutFile > 0 .and. allocated(y%WriteOutput)) then + if (p%UA_OUTS==2 .and. p%unOutFile > 0 .and. allocated(y%WriteOutput)) then write (p%unOutFile,"(F19.6)",ADVANCE='no') t do k=1,size(y%WriteOutput) @@ -3855,10 +3918,10 @@ subroutine UA_WriteOutputToFile(t, p, y) WRITE (p%unOutFile,'()') ! write the line return end if -#endif end subroutine UA_WriteOutputToFile !============================================================================== +! TODO Somehow merge this content with the unsteady aero driver summary file? subroutine UA_WriteAFIParamsToFile(InitInp, AFInfo, ErrStat, ErrMsg) type(AFI_ParameterType), intent(in ) :: AFInfo(:) ! The airfoil parameter data (for all airfoils) type(UA_InitInputType), intent(in ) :: InitInp ! input data for initialization routine @@ -3938,7 +4001,7 @@ subroutine UA_WriteAFIParamsToFile(InitInp, AFInfo, ErrStat, ErrMsg) CALL GetNewUnit( unOutFile, ErrStat, ErrMsg ) IF ( ErrStat /= ErrID_None ) RETURN - CALL OpenFOutFile ( unOutFile, trim(InitInp%OutRootName)//'.UA.sum', ErrStat2, ErrMsg2 ) + CALL OpenFOutFile ( unOutFile, trim(InitInp%OutRootName)//'.sum', ErrStat2, ErrMsg2 ) call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) if (ErrStat >= AbortErrLev) return diff --git a/modules/aerodyn/src/UnsteadyAero_Driver.f90 b/modules/aerodyn/src/UnsteadyAero_Driver.f90 index 1ffac32865..f04e4391b7 100644 --- a/modules/aerodyn/src/UnsteadyAero_Driver.f90 +++ b/modules/aerodyn/src/UnsteadyAero_Driver.f90 @@ -19,10 +19,6 @@ ! limitations under the License. ! !********************************************************************************************************************************** - - - - program UnsteadyAero_Driver use NWTC_Library @@ -31,45 +27,24 @@ program UnsteadyAero_Driver use UnsteadyAero_Types use UnsteadyAero use UA_Dvr_Subs - USE VersionInfo + use VersionInfo - implicit none + use LinDyn - - - - + implicit none ! Variables - integer(IntKi), parameter :: NumInp = 2 ! Number of inputs sent to UA_UpdateStates (must be at least 2) - real(DbKi) :: dt, t, uTimes(NumInp) + real(DbKi) :: t, tnext integer :: i, j, n, iu - type(UA_InitInputType) :: InitInData ! Input data for initialization - type(UA_InitOutputType) :: InitOutData ! Output data from initialization - type(UA_ContinuousStateType) :: x ! Continuous states - type(UA_DiscreteStateType) :: xd ! Discrete states - type(UA_OtherStateType) :: OtherState ! Other/optimization states - type(UA_MiscVarType) :: m ! Misc/optimization variables - type(UA_ParameterType) :: p ! Parameters - type(UA_InputType) :: u(NumInp) ! System inputs - type(UA_OutputType) :: y ! System outputs + + ! --- All Data + type(Dvr_Data) :: dvr + integer(IntKi) :: ErrStat ! Status of error message character(ErrMsgLen) :: ErrMsg ! Error message if ErrStat /= ErrID_None - integer, parameter :: NumAFfiles = 1 - character(1024) :: afNames(NumAFfiles) - type(AFI_ParameterType) :: AFI_Params(NumAFfiles) - integer, allocatable :: AFIndx(:,:) CHARACTER(1024) :: dvrFilename ! Filename and path for the driver input file. This is passed in as a command line argument when running the Driver exe. - TYPE(UA_Dvr_InitInput) :: dvrInitInp ! Initialization data for the driver program - real(DbKi) :: simTime - integer :: nSimSteps character(*), parameter :: RoutineName = 'UnsteadyAero_Driver' - real(DbKi), allocatable :: timeArr(:) - real(ReKi), allocatable :: AOAarr(:) - real(ReKi), allocatable :: Uarr(:) - real(ReKi), allocatable :: OmegaArr(:) - logical :: UA_f_cn ! Should the separation function be computed using Cn or Cl CHARACTER(200) :: git_commit TYPE(ProgDesc), PARAMETER :: version = ProgDesc( 'UnsteadyAero Driver', '', '' ) ! The version number of this program. @@ -80,189 +55,230 @@ program UnsteadyAero_Driver ErrMsg = '' ErrStat = ErrID_None - ! Display the copyright notice CALL DispCopyrightLicense( version%Name ) ! Obtain OpenFAST git commit hash git_commit = QueryGitVersion() ! Tell our users what they're running - CALL WrScr( ' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)//NewLine//' linked with '//TRIM( NWTC_Ver%Name )//NewLine ) + CALL WrScr(' Running '//TRIM( version%Name )//' a part of OpenFAST - '//TRIM(git_Commit)) - ! Parse the driver file if one was provided, if not, then set driver parameters using hardcoded values + ! --- Parse the driver file if one if ( command_argument_count() > 1 ) then call print_help() - call checkError() - end if - - - ! Establish initialization inputs which are fixed for the stand-alone driver, but would be - ! variable for a coupled simulation - InitInData%nNodesPerBlade = 1 - InitInData%numBlades = 1 - - ! Set up initialization data - allocate(AFIndx(InitInData%nNodesPerBlade,InitInData%numBlades), STAT = ErrStat) - if ( ErrStat /= 0 ) then - call SetErrStat( ErrID_Fatal, 'Error trying to allocate InitInData%AFIndx.', ErrStat, ErrMsg, RoutineName) - call checkError() - end if - - allocate(InitInData%c(InitInData%nNodesPerBlade,InitInData%numBlades), STAT = ErrStat) - if ( ErrStat /= 0 ) then - call SetErrStat( ErrID_Fatal, 'Error trying to allocate InitInData%c.', ErrStat, ErrMsg, RoutineName) - call checkError() - end if - - allocate( InitInData%UAOff_innerNode(InitInData%numBlades), InitInData%UAOff_outerNode(InitInData%numBlades), STAT = ErrStat) - if ( ErrStat /= 0 ) then - call SetErrStat( ErrID_Fatal, 'Error trying to allocate UAOff_innerNode and UAOff_outerNode.', ErrStat, ErrMsg, RoutineName) - call checkError() - end if - ! don't turn off UA based on span location: - InitInData%UAOff_innerNode = 0 - InitInData%UAOff_outerNode = InitInData%nNodesPerBlade + 1 - - ! Parse the driver input file and run the simulation based on that file - - if ( command_argument_count() == 1 ) then - - call get_command_argument(1, dvrFilename) - call ReadDriverInputFile( dvrFilename, dvrInitInp, errStat, errMsg ) - call checkError() - InitInData%a_s = dvrInitInp%SpdSound - InitInData%c(1,1) = dvrInitInp%Chord - InitInData%UAMod = dvrInitInp%UAMod - InitInData%Flookup = dvrInitInp%Flookup - - else - - dvrInitInp%OutRootName = './TestingUA_Driver' - InitInData%UAMod = 1 - InitInData%Flookup = .FALSE. - InitInData%a_s = 340.29 ! m/s - InitInData%c(1,1) = 1.0 - - dvrInitInp%InflowVel = 30.0 ! m/s - dvrInitInp%Re = 75 ! million - dvrInitInp%AirFoil1 = './OSU075_FAST.txt' - dvrInitInp%SimMod = 1 - dvrInitInp%NCycles = 3.0 - dvrInitInp%Frequency = 1.2 ! Hz - dvrInitInp%StepsPerCycle= 180 - dvrInitInp%Amplitude = 10.0 ! deg - dvrInitInp%Mean = 2.0 ! deg - dvrInitInp%Phase = 0 ! steps of a cycle - dvrInitInp%InputsFile = '' - - end if - InitInData%OutRootName = dvrInitInp%OutRootName - - InitInData%WrSum = dvrInitInp%SumPrint ! write all the AFI data + call NormStop() + endif + call get_command_argument(1, dvrFilename) + call ReadDriverInputFile( dvrFilename, dvr%p, errStat, errMsg ); call checkError() - - if ( dvrInitInp%SimMod == 1 ) then - ! Using the frequency and NCycles, determine how long the simulation needs to run - simTime = dvrInitInp%NCycles/dvrInitInp%Frequency - nSimSteps = dvrInitInp%StepsPerCycle*dvrInitInp%NCycles ! we could add 1 here to make this a complete cycle - dt = simTime / nSimSteps - - else - ! Read time-series data file with a 1 line header and then each row contains time-step data with 4, white-space-separated columns - ! time, Angle-of-attack, Vrel, omega - call ReadTimeSeriesData( dvrInitInp%InputsFile, nSimSteps, timeArr, AOAarr, Uarr, OmegaArr, errStat, errMsg ) - call checkError() - dt = (timeArr(nSimSteps) - timeArr(1)) / (nSimSteps-1) - nSimSteps = nSimSteps-NumInp + 1 - - end if - - ! Initialize the Airfoil Info Params - afNames(1) = dvrInitInp%AirFoil1 ! All nodes/blades are using the same 2D airfoil - AFIndx(1,1) = 1 - UA_f_cn = (InitInData%UAMod /= UA_HGM).and.(InitInData%UAMod /= UA_OYE) ! HGM and OYE use the separation function based on cl instead of cn - call Init_AFI( InitInData%UAMod, NumAFfiles, afNames, dvrInitInp%UseCm, UA_f_cn, AFI_Params, errStat, errMsg ) - call checkError() + ! --- Driver Parameters + call Dvr_SetParameters(dvr%p, errStat, errMsg); call checkError() - if (dvrInitInp%WrAFITables) then - call WriteAFITables(AFI_Params(1), dvrInitInp%OutRootName, dvrInitInp%UseCm, UA_f_cn) - endif - - - ! Initialize UnsteadyAero (after AFI) - call UA_Init( InitInData, u(1), p, x, xd, OtherState, y, m, dt, AFI_Params, AFIndx, InitOutData, errStat, errMsg ) - call checkError() + ! --- Initialize Elastic Section + if ( dvr%p%SimMod == 3 ) then + call LD_InitInputData(3, dvr%LD_InitInData, errStat, errMsg); call checkError() + dvr%LD_InitInData%dt = dvr%p%dt + dvr%LD_InitInData%IntMethod = 1 ! 1=RK4, TODO expose to user + dvr%LD_InitInData%prefix = '' ! for output channel names + dvr%LD_InitInData%MM = dvr%p%MM + dvr%LD_InitInData%CC = dvr%p%CC + dvr%LD_InitInData%KK = dvr%p%KK + dvr%LD_InitInData%x0 = dvr%p%initPos + dvr%LD_InitInData%xd0 = dvr%p%initVel + dvr%LD_InitInData%activeDOFs = dvr%p%activeDOFs + dvr%LD_InitInData%DOFsNames = (/'x ','y ','th '/) + dvr%LD_InitInData%DOFsUnits = (/'m ','m ','rad'/) + if (dvr%p%MotionMod==MotionMod_File) then + dvr%LD_InitInData%PrescribedMotionFile = dvr%p%MotionTSFile + else + dvr%LD_InitInData%PrescribedMotionFile = '' + endif + call LD_Init(dvr%LD_InitInData, dvr%LD_u(1), dvr%LD_p, dvr%LD_x, dvr%LD_xd, dvr%LD_z, dvr%LD_OtherState, dvr%LD_y, dvr%LD_m, dvr%LD_InitOutData, errStat, errMsg); call checkError() + ! Allocate other inputs of LD + do iu = 2,NumInp + call AllocAry(dvr%LD_u(iu)%Fext, dvr%LD_p%nx, 'Fext', errStat, errMsg); call checkError() + enddo + end if + ! --- Init UA input data based on driver inputs + call driverInputsToUAInitData(dvr%p, dvr%UA_InitInData, dvr%AFI_Params, dvr%AFIndx, errStat, errMsg); call checkError() - if (p%NumOuts <= 0) then - ErrStat = ErrID_Fatal - ErrMsg = "No outputs have been selected. Rebuild the executable with -DUA_OUTS" + ! --- Initialize UnsteadyAero (need AFI) + call UA_Init( dvr%UA_InitInData, dvr%UA_u(1), dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%UA_y, dvr%UA_m, dvr%p%dt, dvr%AFI_Params, dvr%AFIndx, dvr%UA_InitOutData, errStat, errMsg ); call checkError() + if (dvr%UA_p%NumOuts <= 0) then + ErrStat = ErrID_Warn + ErrMsg = "No outputs from UA are generated." call checkError() end if - ! set inputs: + ! --- Driver Outputs + dvr%out%Root = dvr%p%OutRootName + call Dvr_InitializeDriverOutputs(dvr, dvr%out, errStat, errMsg); call checkError() + + i = 1 ! nodes per blade + j = 1 ! number of blades + ! --- Initialize Inputs !u(1) = time at n=1 (t= 0) !u(2) = time at n=0 (t= -dt) !u(3) = time at n=-1 (t= -2dt) if NumInp > 2 + if ( dvr%p%SimMod == 3 ) then + ! General inputs + do iu = 1, NumInp !u(NumInp) is overwritten in time-sim loop, so no need to init here + dvr%uTimes(iu) = (2-iu-1)*dvr%p%dt + enddo + ! Inflow "inputs" + do iu = 1,NumInp + call setInflow(t=dvr%uTimes(iu), p=dvr%p, m=dvr%m, U0=dvr%U0(iu,:)) + enddo + ! UA inputs at t=0, stored in u(1) + do iu = 1, NumInp-1 !u(NumInp) is overwritten in time-sim loop, so no need to init here + call setUAinputs(dvr%U0(iu,:), dvr%LD_x, dvr%p, dvr%m, dvr%UA_u(iu)) + enddo + ! LD inputs + do iu = 1, NumInp-1 !u(NumInp) is overwritten in time-sim loop, so no need to init here + call UA_CalcOutput(i, j, dvr%uTimes(iu), dvr%UA_u(iu), dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%AFI_Params(dvr%AFIndx(i,j)), dvr%UA_y, dvr%UA_m, errStat, errMsg ); call checkError() + call setLDinputs(dvr%U0(iu,:), dvr%LD_x, dvr%UA_y, dvr%p, dvr%m, dvr%LD_u(iu)) + enddo - DO iu = 1, NumInp-1 !u(NumInp) is overwritten in time-sim loop, so no need to init here - call setUAinputs(2-iu, u(iu), uTimes(iu), dt, dvrInitInp, timeArr, AOAarr, Uarr, OmegaArr, errStat, errMsg) - call checkError() - END DO - - ! Set inputs which do not vary with node or time + else + ! UA inputs at t=0, stored in u(1) + do iu = 1, NumInp-1 !u(NumInp) is overwritten in time-sim loop, so no need to init here + call setUAinputsAlphaSim(2-iu, dvr%UA_u(iu), dvr%uTimes(iu), dvr%p, dvr%m, errStat, errMsg); call checkError() + end do + endif - ! time marching loop - do n = 1, nSimSteps + ! --- Time marching loop + call Dvr_InitializeOutputs(dvr%out, dvr%p%numSteps, errStat, errMsg) - i = 1 ! nodes per blade - j = 1 ! number of blades - - ! set inputs: - DO iu = NumInp-1, 1, -1 - u( iu+1) = u( iu) - uTimes(iu+1) = uTimes(iu) - END DO - - ! first value of uTimes/u contain inputs at t+dt - call setUAinputs(n+1, u(1), uTimes(1), dt, dvrInitInp, timeArr, AOAarr, Uarr, OmegaArr, errStat, errMsg) - call checkError() - - t = uTimes(2) + if ( dvr%p%SimMod == 3 ) then + + ! --- Time marching loop + call WrScr(' Aeroelastic simulation - TMax = '//trim(num2lstr(dvr%p%numSteps*dvr%p%dt))) + do n = 1, dvr%p%numSteps + ! --- Set inputs at t by storing in u(2) what was in u(1) at previous time step + !u(1) = time at n=n+1 (t=t+dt) + !u(2) = time at n=n (t=t ) + do iu = NumInp-1, 1, -1 + dvr%uTimes(iu+1) = dvr%uTimes(iu) + dvr%U0( iu+1,:)= dvr%U0(iu,:) + dvr%UA_u( iu+1) = dvr%UA_u( iu) + dvr%LD_u( iu+1) = dvr%LD_u( iu) + end do + + ! ---------------------------------------------------------------------------- + ! --- t + ! ---------------------------------------------------------------------------- + iu = 2 ! Index 2 is t + dvr%uTimes(iu) = (n -1)*dvr%p%dt ! t + t = dvr%uTimes(iu) ! t(2)= t + ! --- Calc Outputs at t ! Use existing states to compute the outputs - call UA_CalcOutput(i, j, t, u(2), p, x, xd, OtherState, AFI_Params(AFIndx(i,j)), y, m, errStat, errMsg ) - call checkError() - + call UA_CalcOutput(i, j, t, dvr%UA_u(iu), dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%AFI_Params(dvr%AFIndx(i,j)), dvr%UA_y, dvr%UA_m, errStat, errMsg ); call checkError() + ! "True" force based on UA outputs - Also compute Misc outputs + !call AeroKinetics(dvr%U0(iu,:), dvr%LD_x%q(1:3), dvr%LD_x%q(4:6), (/dvr%UA_y%Cl, dvr%UA_y%Cd, dvr%UA_y%Cm/), dvr%p, dvr%m) + call setLDinputs(dvr%U0(iu,:), dvr%LD_x, dvr%UA_y, dvr%p, dvr%m, dvr%LD_u(iu)) + ! Use existing states to compute the outputs + call LD_CalcOutput(t, dvr%LD_u(iu), dvr%LD_p, dvr%LD_x, dvr%LD_xd, dvr%LD_z, dvr%LD_OtherState, dvr%LD_y, dvr%LD_m, errStat, errMsg); call checkError() ! Generate file outputs - call UA_WriteOutputToFile(t, p, y) + call UA_WriteOutputToFile(t, dvr%UA_p, dvr%UA_y) + ! Write/Store outputs + call Dvr_WriteOutputs(n, t, dvr, dvr%out, errStat, errMsg); call checkError() - - ! Prepare states for next time step - call UA_UpdateStates(i, j, t, n, u, uTimes, p, x, xd, OtherState, AFI_Params(AFIndx(i,j)), m, errStat, errMsg ) - call checkError() + ! Backup at t - if iteration needed + !call backupStates() + ! ---------------------------------------------------------------------------- + ! --- From t to t+dt + ! ---------------------------------------------------------------------------- + iu = 1 ! Index 1 is t+dt + dvr%uTimes(iu) = (n+1-1)*dvr%p%dt ! t+dt + tnext = dvr%uTimes(iu) ! t(2)= t+dt + ! --- Set inputs at t+dt in u(1) + ! Inflow inputs + call setInflow(t=tnext, p=dvr%p, m=dvr%m, U0=dvr%U0(iu,:)) + ! LinDyn inputs at t+dt + call LD_Input_ExtrapInterp(dvr%LD_u(:), dvr%uTimes(:), dvr%LD_u(iu), tnext, errStat, errMsg); call checkError() + + ! --- Integrate LinDyn from t to t+dt + call LD_UpdateStates(t, n, dvr%LD_u, dvr%uTimes, dvr%LD_p, dvr%LD_x, dvr%LD_xd, dvr%LD_z, dvr%LD_OtherState, dvr%LD_m, errStat, errMsg); call checkError() + ! Calc LinDyn outputs at t+dt + call LD_CalcOutput(t, dvr%LD_u(iu), dvr%LD_p, dvr%LD_x, dvr%LD_xd, dvr%LD_z, dvr%LD_OtherState, dvr%LD_y, dvr%LD_m, errStat, errMsg); call checkError() + + ! --- Set UA Inputs at t+dt + call setUAinputs(dvr%U0(iu,:), dvr%LD_x, dvr%p, dvr%m, dvr%UA_u(iu)) + + ! --- Integrate UA from t to t+dt + call UA_UpdateStates(i, j, t, n, dvr%UA_u, dvr%uTimes, dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%AFI_Params(dvr%AFIndx(i,j)), dvr%UA_m, errStat, errMsg ); call checkError() + + ! --- One extra iteration with better LD inputs at t+dt + !call UA_CalcOutput(i, j, tnext, dvr%UA_u(iu), dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%AFI_Params(dvr%AFIndx(i,j)), dvr%UA_y, dvr%UA_m, errStat, errMsg ); call checkError() + !call setLDinputs(dvr%U0(iu,:), dvr%LD_x, dvr%UA_y, dvr%p, dvr%m, dvr%LD_u(iu)) + !call restoreLDStates() + !call LD_UpdateStates(t, n, dvr%LD_u, dvr%uTimes, dvr%LD_p, dvr%LD_x, dvr%LD_xd, dvr%LD_z, dvr%LD_OtherState, dvr%LD_m, errStat, errMsg); call checkError() + !call LD_CalcOutput(tnext, dvr%LD_u(iu), dvr%LD_p, dvr%LD_x, dvr%LD_xd, dvr%LD_z, dvr%LD_OtherState, dvr%LD_y, dvr%LD_m, errStat, errMsg); call checkError() + !call setUAinputs(dvr%U0(iu,:), dvr%LD_x, dvr%p, dvr%m, dvr%UA_u(iu)) + !call restoreUAStates() + !call UA_UpdateStates(i, j, t, n, dvr%UA_u, dvr%uTimes, dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%AFI_Params(dvr%AFIndx(i,j)), dvr%UA_m, errStat, errMsg ); call checkError() + end do + + else + ! --- Time marching loop + call WrScr(' UA time simulation - TMax = '//trim(num2lstr(dvr%p%numSteps*dvr%p%dt))) + do n = 1, dvr%p%numSteps + + ! --- Set inputs at t by storing in u(2) what was in u(1) at previous time step + !u(1) = time at n=n+1 (t=t+dt) + !u(2) = time at n=n (t=t ) + do iu = NumInp-1, 1, -1 + dvr%UA_u( iu+1) = dvr%UA_u( iu) + dvr%uTimes(iu+1) = dvr%uTimes(iu) + end do + + ! first value of uTimes/u contain inputs at t+dt + call setUAinputsAlphaSim(n+1, dvr%UA_u(1), dvr%uTimes(1), dvr%p, dvr%m, errStat, errMsg); call checkError() + + t = dvr%uTimes(2) + + ! Use existing states to compute the outputs + call UA_CalcOutput(i, j, t, dvr%UA_u(2), dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%AFI_Params(dvr%AFIndx(i,j)), dvr%UA_y, dvr%UA_m, errStat, errMsg ); call checkError() - - end do - - - !------------------------------------------------------------------------------------------------- - ! Close our output file - !------------------------------------------------------------------------------------------------- + ! Generate file outputs + call UA_WriteOutputToFile(t, dvr%UA_p, dvr%UA_y) + ! Write/Store outputs + call Dvr_WriteOutputs(n, t, dvr, dvr%out, errStat, errMsg); call checkError() + + ! Prepare states for next time step + call UA_UpdateStates(i, j, t, n, dvr%UA_u, dvr%uTimes, dvr%UA_p, dvr%UA_x, dvr%UA_xd, dvr%UA_OtherState, dvr%AFI_Params(dvr%AFIndx(i,j)), dvr%UA_m, errStat, errMsg ); call checkError() + + end do + endif + call Dvr_EndSim(dvr, errStat, errMsg) + ! --- Exit call Cleanup() call NormStop() - - contains - + +contains + subroutine backupStates() + call UA_CopyContState (dvr%UA_x , dvr%UA_x_swp , MESH_UPDATECOPY , errStat , errMsg) + call UA_CopyDiscState (dvr%UA_xd , dvr%UA_xd_swp , MESH_UPDATECOPY , errStat , errMsg) + call UA_CopyOtherState(dvr%UA_OtherState , dvr%UA_OtherState_swp , MESH_UPDATECOPY , errStat , errMsg) + call LD_CopyContState (dvr%LD_x , dvr%LD_x_swp , MESH_UPDATECOPY , errStat , errMsg) + call LD_CopyOtherState(dvr%LD_OtherState , dvr%LD_OtherState_swp , MESH_UPDATECOPY , errStat , errMsg) + end subroutine + subroutine restoreUAStates() + call UA_CopyContState (dvr%UA_x_swp , dvr%UA_x , MESH_UPDATECOPY , errStat , errMsg) + call UA_CopyDiscState (dvr%UA_xd_swp , dvr%UA_xd , MESH_UPDATECOPY , errStat , errMsg) + call UA_CopyOtherState(dvr%UA_OtherState_swp, dvr%UA_OtherState , MESH_UPDATECOPY , errStat , errMsg) + end subroutine + subroutine restoreLDStates() + call LD_CopyContState (dvr%LD_x_swp , dvr%LD_x , MESH_UPDATECOPY , errStat , errMsg) + call LD_CopyOtherState(dvr%LD_OtherState_swp, dvr%LD_OtherState , MESH_UPDATECOPY , errStat , errMsg) + end subroutine !==================================================================================================== subroutine Cleanup() - ! The routine cleans up the module echo file and resets the NWTC_Library, reattaching it to - ! any existing echo information - !---------------------------------------------------------------------------------------------------- - call UA_End(p) - - ! probably should also deallocate driver variables here + call UA_End(dvr%UA_p) + ! probably should also deallocate driver variables here... end subroutine Cleanup @@ -282,94 +298,6 @@ subroutine checkError() end subroutine checkError !---------------------------------------------------------------------------------------------------- - subroutine setUAinputs(n,u,t,dt,dvrInitInp,timeArr,AOAarr,Uarr,OmegaArr,errStat,errMsg) - - integer, intent(in) :: n - type(UA_InputType), intent(inout) :: u ! System inputs - real(DbKi), intent( out) :: t - real(DbKi), intent(in) :: dt - TYPE(UA_Dvr_InitInput), intent(in) :: dvrInitInp ! Initialization data for the driver program - real(DbKi), intent(in), allocatable :: timeArr(:) - real(ReKi), intent(in), allocatable :: AOAarr(:) - real(ReKi), intent(in), allocatable :: Uarr(:) - real(ReKi), intent(in), allocatable :: OmegaArr(:) - integer, intent(out) :: errStat - character(len=*), intent(out) :: errMsg - integer :: indx - real(ReKi) :: phase - real(ReKi) :: d_ref2AC - real(ReKi) :: alpha_ref - real(ReKi) :: U_ref - real(ReKi) :: v_ref(2) - real(ReKi) :: v_34(2) - logical, parameter :: OscillationAtMidChord=.true. ! for legacy, use false - logical, parameter :: VelocityAt34 =.true. ! for legacy, use false - - ! Initialize error handling variables - ErrMsg = '' - ErrStat = ErrID_None - - u%UserProp = 0 - u%Re = dvrInitInp%Re - - if ( dvrInitInp%SimMod == 1 ) then - if (OscillationAtMidChord) then - d_ref2AC =-0.25_ReKi ! -0.25: oscillations at mid_chord - else - d_ref2AC = 0.0_ReKi ! 0: oscillations at AC - endif - U_ref = dvrInitInp%InflowVel ! m/s - - t = (n-1)*dt - phase = (n+dvrInitInp%Phase-1)*2*pi/dvrInitInp%StepsPerCycle - alpha_ref = (dvrInitInp%Amplitude * sin(phase) + dvrInitInp%Mean)*D2R ! This needs to be in radians - v_ref(1) = sin(alpha_ref)*U_ref - v_ref(2) = cos(alpha_ref)*U_ref - u%omega = dvrInitInp%Amplitude * cos(phase) * 2*pi/dvrInitInp%StepsPerCycle / dt * D2R ! This needs to be in radians derivative: d_alpha /d_t - - u%v_ac(1) = v_ref(1) + u%omega * d_ref2AC* dvrInitInp%Chord - u%v_ac(2) = v_ref(2) - - v_34(1) = u%v_ac(1) + u%omega * 0.5* dvrInitInp%Chord - v_34(2) = u%v_ac(2) - - - u%alpha = atan2(u%v_ac(1), u%v_ac(2) ) ! - if (VelocityAt34) then - u%U = sqrt(v_34(1)**2 + v_34(2)**2) ! Using U at 3/4 - else - u%U = sqrt(u%v_ac(1)**2 + u%v_ac(2)**2) ! Using U at 1/4 - endif - - - else - ! check optional variables and allocation status - if (all( (/ allocated(timeArr),allocated(AOAarr),allocated(OmegaArr),allocated(Uarr) /) )) then - - indx = min(n,size(timeArr)) - indx = max(1, indx) ! use constant data at initialization - - ! Load timestep data from the time-series inputs which were previous read from input file - t = timeArr(indx) - u%alpha = AOAarr(indx)*pi/180.0 ! This needs to be in radians - u%omega = OmegaArr(indx) - u%U = Uarr(indx) - if (n> size(timeArr)) then - t = t + dt*(n - size(timeArr) ) ! update for NumInp>1; - elseif (n < 1) then - t = (n-1)*dt - end if - u%v_ac(1) = sin(u%alpha)*u%U - u%v_ac(2) = cos(u%alpha)*u%U - else - errStat = ErrID_Fatal - errMsg = 'mandatory input arrays are not allocated: timeArr,AOAarr,OmegaArr,Uarr' - end if - - end if - - end subroutine setUAinputs - !---------------------------------------------------------------------------------------------------- subroutine print_help() print '(a)', 'usage: ' diff --git a/modules/aerodyn/src/UnsteadyAero_Registry.txt b/modules/aerodyn/src/UnsteadyAero_Registry.txt index d3eb0ef03a..1c5c704c63 100644 --- a/modules/aerodyn/src/UnsteadyAero_Registry.txt +++ b/modules/aerodyn/src/UnsteadyAero_Registry.txt @@ -17,6 +17,7 @@ usefrom AirfoilInfo_Registry.txt # # +param UnsteadyAero/UA - INTEGER UA_None - 0 - "Steady aerodynamics, using same angle of attack convention as UA" - param UnsteadyAero/UA - INTEGER UA_Baseline - 1 - "UAMod = 1 [Baseline model (Original)]" - param UnsteadyAero/UA - INTEGER UA_Gonzalez - 2 - "UAMod = 2 [Gonzalez's variant (changes in Cn,Cc,Cm)]" - param UnsteadyAero/UA - INTEGER UA_MinnemaPierce - 3 - "[Minnema/Pierce variant (changes in Cc and Cm)]" - @@ -32,6 +33,7 @@ param UnsteadyAero/UA - INTEGER UA_BV typedef UnsteadyAero/UA InitInputType DbKi dt - - - "time step" s typedef ^ ^ CHARACTER(1024) OutRootName - - - "Supplied by Driver: The name of the root file (without extension) including the full path" - typedef ^ ^ ReKi c {:}{:} - - "Chord length at node" m +typedef ^ ^ ReKi d_34_to_ac - 0.5 - "Distance from 3/4 chord to aerodynamic center (typically 0.5) in chord length (no dimension)" - typedef ^ ^ INTEGER numBlades - - - "Number nodes of all blades" - typedef ^ ^ INTEGER nNodesPerBlade - - - "Number nodes per blades" - typedef ^ ^ INTEGER UAMod - - - "Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema]" - @@ -41,13 +43,14 @@ typedef ^ ^ Logical typedef ^ ^ LOGICAL WrSum - .false. - "Write UA AFI parameters to summary file?" - typedef ^ ^ INTEGER UAOff_innerNode {:} - - "Last node on each blade where UA should be turned off based on span location from blade root (0 if always on)" - typedef ^ ^ INTEGER UAOff_outerNode {:} - - "First node on each blade where UA should be turned off based on span location from blade tip (>nNodesPerBlade if always on)" - +typedef ^ ^ IntKi UA_OUTS - 0 - "Store write outputs 0=None, 1=WriteOutpus, 2=WriteToFile" - # # Define outputs from the initialization routine here: # typedef ^ InitOutputType ProgDesc Version - - - "Version structure" - -typedef ^ InitOutputType CHARACTER(19) WriteOutputHdr {:} - - "The is the list of all UA-related output channel header strings (includes all sub-module channels)" - -typedef ^ ^ CHARACTER(19) WriteOutputUnt {:} - - "The is the list of all UA-related output channel unit strings (includes all sub-module channels)" - +typedef ^ InitOutputType CHARACTER(ChanLen) WriteOutputHdr {:} - - "The is the list of all UA-related output channel header strings (includes all sub-module channels)" - +typedef ^ ^ CHARACTER(ChanLen) WriteOutputUnt {:} - - "The is the list of all UA-related output channel unit strings (includes all sub-module channels)" - # Variables local to the Kelvin Chain: @@ -189,6 +192,7 @@ typedef ^ MiscVarType ReKi # Define parameters here: typedef ^ ParameterType DbKi dt - - - "time step" s typedef ^ ^ ReKi c {:}{:} - - "Chord length at node" m +typedef ^ ^ ReKi d_34_to_ac - 0.5 - "Distance from 3/4 chord to aerodynamic center (typically 0.5) in chord length (no dimension)" - typedef ^ ^ INTEGER numBlades - - - "Number nodes of all blades" - typedef ^ ^ INTEGER nNodesPerBlade - - - "Number nodes per blades" - typedef ^ ^ INTEGER UAMod - - - "Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema]" - @@ -205,6 +209,7 @@ typedef ^ ParameterType IntKi typedef ^ ^ LOGICAL UA_off_forGood {:}{:} - - "logical flag indicating if UA is off for good" - typedef ^ ^ INTEGER lin_xIndx {:}{:} - - "array to indicate which state to perturb for UA" - typedef ^ ^ R8Ki dx {5} - - "array to indicate size of state perturbations" - +typedef ^ ^ IntKi UA_OUTS - 0 - "Store write outputs 0=None, 1=WriteOutpus, 2=WriteToFile" - # ..... Inputs .................................................................................................................... # Define inputs that are contained on the mesh here: diff --git a/modules/aerodyn/src/UnsteadyAero_Types.f90 b/modules/aerodyn/src/UnsteadyAero_Types.f90 index 8fad9bcdcf..eac8874e36 100644 --- a/modules/aerodyn/src/UnsteadyAero_Types.f90 +++ b/modules/aerodyn/src/UnsteadyAero_Types.f90 @@ -34,6 +34,7 @@ MODULE UnsteadyAero_Types USE AirfoilInfo_Types USE NWTC_Library IMPLICIT NONE + INTEGER(IntKi), PUBLIC, PARAMETER :: UA_None = 0 ! Steady aerodynamics, using same angle of attack convention as UA [-] INTEGER(IntKi), PUBLIC, PARAMETER :: UA_Baseline = 1 ! UAMod = 1 [Baseline model (Original)] [-] INTEGER(IntKi), PUBLIC, PARAMETER :: UA_Gonzalez = 2 ! UAMod = 2 [Gonzalez's variant (changes in Cn,Cc,Cm)] [-] INTEGER(IntKi), PUBLIC, PARAMETER :: UA_MinnemaPierce = 3 ! [Minnema/Pierce variant (changes in Cc and Cm)] [-] @@ -46,6 +47,7 @@ MODULE UnsteadyAero_Types REAL(DbKi) :: dt = 0.0_R8Ki !< time step [s] CHARACTER(1024) :: OutRootName !< Supplied by Driver: The name of the root file (without extension) including the full path [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: c !< Chord length at node [m] + REAL(ReKi) :: d_34_to_ac = 0.5 !< Distance from 3/4 chord to aerodynamic center (typically 0.5) in chord length (no dimension) [-] INTEGER(IntKi) :: numBlades = 0_IntKi !< Number nodes of all blades [-] INTEGER(IntKi) :: nNodesPerBlade = 0_IntKi !< Number nodes per blades [-] INTEGER(IntKi) :: UAMod = 0_IntKi !< Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema] [-] @@ -55,13 +57,14 @@ MODULE UnsteadyAero_Types LOGICAL :: WrSum = .false. !< Write UA AFI parameters to summary file? [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: UAOff_innerNode !< Last node on each blade where UA should be turned off based on span location from blade root (0 if always on) [-] INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: UAOff_outerNode !< First node on each blade where UA should be turned off based on span location from blade tip (>nNodesPerBlade if always on) [-] + INTEGER(IntKi) :: UA_OUTS = 0 !< Store write outputs 0=None, 1=WriteOutpus, 2=WriteToFile [-] END TYPE UA_InitInputType ! ======================= ! ========= UA_InitOutputType ======= TYPE, PUBLIC :: UA_InitOutputType TYPE(ProgDesc) :: Version !< Version structure [-] - CHARACTER(19) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< The is the list of all UA-related output channel header strings (includes all sub-module channels) [-] - CHARACTER(19) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< The is the list of all UA-related output channel unit strings (includes all sub-module channels) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< The is the list of all UA-related output channel header strings (includes all sub-module channels) [-] + CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< The is the list of all UA-related output channel unit strings (includes all sub-module channels) [-] END TYPE UA_InitOutputType ! ======================= ! ========= UA_KelvinChainType ======= @@ -208,6 +211,7 @@ MODULE UnsteadyAero_Types TYPE, PUBLIC :: UA_ParameterType REAL(DbKi) :: dt = 0.0_R8Ki !< time step [s] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: c !< Chord length at node [m] + REAL(ReKi) :: d_34_to_ac = 0.5 !< Distance from 3/4 chord to aerodynamic center (typically 0.5) in chord length (no dimension) [-] INTEGER(IntKi) :: numBlades = 0_IntKi !< Number nodes of all blades [-] INTEGER(IntKi) :: nNodesPerBlade = 0_IntKi !< Number nodes per blades [-] INTEGER(IntKi) :: UAMod = 0_IntKi !< Model for the dynamic stall equations [1 = Leishman/Beddoes, 2 = Gonzalez, 3 = Minnema] [-] @@ -224,6 +228,7 @@ MODULE UnsteadyAero_Types LOGICAL , DIMENSION(:,:), ALLOCATABLE :: UA_off_forGood !< logical flag indicating if UA is off for good [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: lin_xIndx !< array to indicate which state to perturb for UA [-] REAL(R8Ki) , DIMENSION(1:5) :: dx = 0.0_R8Ki !< array to indicate size of state perturbations [-] + INTEGER(IntKi) :: UA_OUTS = 0 !< Store write outputs 0=None, 1=WriteOutpus, 2=WriteToFile [-] END TYPE UA_ParameterType ! ======================= ! ========= UA_InputType ======= @@ -273,6 +278,7 @@ subroutine UA_CopyInitInput(SrcInitInputData, DstInitInputData, CtrlCode, ErrSta end if DstInitInputData%c = SrcInitInputData%c end if + DstInitInputData%d_34_to_ac = SrcInitInputData%d_34_to_ac DstInitInputData%numBlades = SrcInitInputData%numBlades DstInitInputData%nNodesPerBlade = SrcInitInputData%nNodesPerBlade DstInitInputData%UAMod = SrcInitInputData%UAMod @@ -304,6 +310,7 @@ subroutine UA_CopyInitInput(SrcInitInputData, DstInitInputData, CtrlCode, ErrSta end if DstInitInputData%UAOff_outerNode = SrcInitInputData%UAOff_outerNode end if + DstInitInputData%UA_OUTS = SrcInitInputData%UA_OUTS end subroutine subroutine UA_DestroyInitInput(InitInputData, ErrStat, ErrMsg) @@ -332,6 +339,7 @@ subroutine UA_PackInitInput(RF, Indata) call RegPack(RF, InData%dt) call RegPack(RF, InData%OutRootName) call RegPackAlloc(RF, InData%c) + call RegPack(RF, InData%d_34_to_ac) call RegPack(RF, InData%numBlades) call RegPack(RF, InData%nNodesPerBlade) call RegPack(RF, InData%UAMod) @@ -341,6 +349,7 @@ subroutine UA_PackInitInput(RF, Indata) call RegPack(RF, InData%WrSum) call RegPackAlloc(RF, InData%UAOff_innerNode) call RegPackAlloc(RF, InData%UAOff_outerNode) + call RegPack(RF, InData%UA_OUTS) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -355,6 +364,7 @@ subroutine UA_UnPackInitInput(RF, OutData) call RegUnpack(RF, OutData%dt); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%OutRootName); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%c); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%d_34_to_ac); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%numBlades); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%nNodesPerBlade); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%UAMod); if (RegCheckErr(RF, RoutineName)) return @@ -364,6 +374,7 @@ subroutine UA_UnPackInitInput(RF, OutData) call RegUnpack(RF, OutData%WrSum); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%UAOff_innerNode); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%UAOff_outerNode); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%UA_OUTS); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine UA_CopyInitOutput(SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg) @@ -1927,6 +1938,7 @@ subroutine UA_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) end if DstParamData%c = SrcParamData%c end if + DstParamData%d_34_to_ac = SrcParamData%d_34_to_ac DstParamData%numBlades = SrcParamData%numBlades DstParamData%nNodesPerBlade = SrcParamData%nNodesPerBlade DstParamData%UAMod = SrcParamData%UAMod @@ -1965,6 +1977,7 @@ subroutine UA_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) DstParamData%lin_xIndx = SrcParamData%lin_xIndx end if DstParamData%dx = SrcParamData%dx + DstParamData%UA_OUTS = SrcParamData%UA_OUTS end subroutine subroutine UA_DestroyParam(ParamData, ErrStat, ErrMsg) @@ -1992,6 +2005,7 @@ subroutine UA_PackParam(RF, Indata) if (RF%ErrStat >= AbortErrLev) return call RegPack(RF, InData%dt) call RegPackAlloc(RF, InData%c) + call RegPack(RF, InData%d_34_to_ac) call RegPack(RF, InData%numBlades) call RegPack(RF, InData%nNodesPerBlade) call RegPack(RF, InData%UAMod) @@ -2008,6 +2022,7 @@ subroutine UA_PackParam(RF, Indata) call RegPackAlloc(RF, InData%UA_off_forGood) call RegPackAlloc(RF, InData%lin_xIndx) call RegPack(RF, InData%dx) + call RegPack(RF, InData%UA_OUTS) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -2021,6 +2036,7 @@ subroutine UA_UnPackParam(RF, OutData) if (RF%ErrStat /= ErrID_None) return call RegUnpack(RF, OutData%dt); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%c); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%d_34_to_ac); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%numBlades); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%nNodesPerBlade); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%UAMod); if (RegCheckErr(RF, RoutineName)) return @@ -2037,6 +2053,7 @@ subroutine UA_UnPackParam(RF, OutData) call RegUnpackAlloc(RF, OutData%UA_off_forGood); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%lin_xIndx); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%dx); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%UA_OUTS); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine UA_CopyInput(SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg) diff --git a/modules/awae/src/AWAE.f90 b/modules/awae/src/AWAE.f90 index b8a40c272e..62f055188c 100644 --- a/modules/awae/src/AWAE.f90 +++ b/modules/awae/src/AWAE.f90 @@ -958,6 +958,9 @@ subroutine AWAE_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitO IfW_InitInp%lidar%HubPosition = 0.0_ReKi IfW_InitInp%lidar%SensorType = SensorType_None IfW_InitInp%Use4Dext = .false. + IfW_InitInp%MHK = MHK_None + IfW_InitInp%WtrDpth = 0.0_ReKi + IfW_InitInp%MSL2SWL = 0.0_ReKi if ( p%Mod_AmbWind == 2 ) then ! one InflowWind module diff --git a/modules/beamdyn/src/BeamDyn.f90 b/modules/beamdyn/src/BeamDyn.f90 index 35f1c75d86..33ff645fb6 100644 --- a/modules/beamdyn/src/BeamDyn.f90 +++ b/modules/beamdyn/src/BeamDyn.f90 @@ -59,7 +59,7 @@ MODULE BeamDyn ! follow the moving BladeRootMotion mesh. This requires changing the states after an UpdateStates call to be relative to ! the new BladeRootMotion mesh orientation and position. ! Upadate the reference frame after each State update (or use the old method)? - LOGICAL, PARAMETER :: ChangeRefFrame = .true. + LOGICAL, PARAMETER :: ChangeRefFrame = .false. CONTAINS @@ -94,7 +94,6 @@ SUBROUTINE BD_Init( InitInp, u, p, x, xd, z, OtherState, y, MiscVar, Interval, I REAL(BDKi) :: temp_CRV(3) REAL(BDKi),ALLOCATABLE :: GLL_nodes(:) REAL(BDKi) :: TmpDCM(3,3) - REAL(BDKi) :: denom LOGICAL :: QuasiStaticInitialized !< True if quasi-static solution was found @@ -153,7 +152,7 @@ SUBROUTINE BD_Init( InitInp, u, p, x, xd, z, OtherState, y, MiscVar, Interval, I ! set mass and stiffness matrices: p%Stif0_QP and p%Mass0_QP call InitializeMassStiffnessMatrices(InputFileData, p, ErrStat2,ErrMsg2); if (Failed()) return - ! Set the initial displacements: p%uu0, p%E10 + ! Set the initial displacements: p%uu0, p%rrN0, p%E10 CALL BD_QuadraturePointDataAt0(p) @@ -163,8 +162,6 @@ SUBROUTINE BD_Init( InitInp, u, p, x, xd, z, OtherState, y, MiscVar, Interval, I CALL BD_ComputeBladeMassNew( p, ErrStat2, ErrMsg2 ); if (Failed()) return !computes p%blade_mass,p%blade_CG,p%blade_IN - ! Actuator - if (p%UsePitchAct) then ! Calculate the pitch angle @@ -591,12 +588,8 @@ subroutine InitializeNodalLocations(member_total,kp_member,kp_coordinate,p,GLL_n tangent = tangent / TwoNorm(tangent) - ! Calculate the node initial rotation CALL BD_ComputeIniNodalCrv(tangent, twist, temp_CRV, ErrStat, ErrMsg) - - ! Store rotation in node initial position vector and save node twist p%uuN0(4:6,i,elem) = temp_CRV - p%twN0(i,elem) = twist enddo @@ -733,11 +726,11 @@ SUBROUTINE BD_InitShpDerJaco( GLL_Nodes, p ) CALL BD_diffmtc(p%nodes_per_elem,GLL_nodes,p%QPtN,p%nqp,p%Shp,p%ShpDer) - ! Calculate the Jacobian relating element axial length to real coordinates DO nelem = 1,p%elem_total DO idx_qp = 1, p%nqp - DO i=1,3 - Gup0(i) = dot_product(p%ShpDer(:,idx_qp), p%uuN0(i,:,nelem)) + Gup0(:) = 0.0_BDKi + DO i=1,p%nodes_per_elem + Gup0(:) = Gup0(:) + p%ShpDer(i,idx_qp)*p%uuN0(1:3,i,nelem) ENDDO p%Jacobian(idx_qp,nelem) = TwoNorm(Gup0) ENDDO @@ -894,11 +887,10 @@ subroutine SetParameters(InitInp, InputFileData, p, OtherState, ErrStat, ErrMsg) INTEGER(IntKi) :: i, j ! generic counter index INTEGER(IntKi) :: indx ! counter into index array (p%NdIndx) INTEGER(IntKi) :: nUniqueQP ! number of unique quadrature points (not double-counting nodes at element boundaries) - + REAL(BDKi) :: denom integer(intKi) :: ErrStat2 ! temporary Error status character(ErrMsgLen) :: ErrMsg2 ! temporary Error message character(*), parameter :: RoutineName = 'SetParameters' - real(DbKi) :: denom @@ -929,6 +921,7 @@ subroutine SetParameters(InitInp, InputFileData, p, OtherState, ErrStat, ErrMsg) p%RotStates = InputFileData%RotStates ! Rotate states in linearization? + if (ChangeRefFrame) p%RotStates = .true. p%RelStates = InputFileData%RelStates ! Define states relative to root motion in linearization? p%rhoinf = InputFileData%rhoinf ! Numerical damping coefficient: [0,1]. No numerical damping if rhoinf = 1; maximum numerical damping if rhoinf = 0. @@ -969,25 +962,7 @@ subroutine SetParameters(InitInp, InputFileData, p, OtherState, ErrStat, ErrMsg) p%dof_elem = p%dof_node * p%nodes_per_elem p%rot_elem = (p%dof_node/2) * p%nodes_per_elem - ! Actuator - p%UsePitchAct = InputFileData%UsePitchAct - if (p%UsePitchAct) then - p%pitchK = InputFileData%pitchK - p%pitchC = InputFileData%pitchC - p%pitchJ = InputFileData%pitchJ - ! calculate (I-hA)^-1 - p%torqM(1,1) = p%pitchJ + p%pitchC*p%dt - p%torqM(2,1) = -p%pitchK * p%dt - p%torqM(1,2) = p%pitchJ * p%dt - p%torqM(2,2) = p%pitchJ - denom = p%pitchJ + p%pitchC*p%dt + p%pitchK*p%dt**2 - if (EqualRealNos(denom,0.0_BDKi)) then - call SetErrStat(ErrID_Fatal,"Cannot invert matrix for pitch actuator: J+c*dt+k*dt^2 is zero.",ErrStat,ErrMsg,RoutineName) - else - p%torqM(:,:) = p%torqM / denom - end if - end if !................................ ! allocate some parameter arrays @@ -1009,7 +984,7 @@ subroutine SetParameters(InitInp, InputFileData, p, OtherState, ErrStat, ErrMsg) CALL AllocAry(p%uuN0, p%dof_node,p%nodes_per_elem, p%elem_total,'uuN0 (initial position) array',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL AllocAry(p%twN0, p%nodes_per_elem, p%elem_total,'twN0 (initial twist) array',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + CALL AllocAry(p%rrN0, (p%dof_node/2),p%nodes_per_elem, p%elem_total,'p%rrN0',ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL AllocAry(p%uu0, p%dof_node, p%nqp, p%elem_total,'p%uu0', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL AllocAry(p%E10, (p%dof_node/2),p%nqp, p%elem_total,'p%E10', ErrStat2,ErrMsg2); CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) @@ -1147,6 +1122,26 @@ subroutine SetParameters(InitInp, InputFileData, p, OtherState, ErrStat, ErrMsg) ! set parameters for pitch actuator: !............................................... + ! Actuator + p%UsePitchAct = InputFileData%UsePitchAct + if (p%UsePitchAct) then + p%pitchK = InputFileData%pitchK + p%pitchC = InputFileData%pitchC + p%pitchJ = InputFileData%pitchJ + + ! calculate (I-hA)^-1 + p%torqM(1,1) = p%pitchJ + p%pitchC*p%dt + p%torqM(2,1) = -p%pitchK * p%dt + p%torqM(1,2) = p%pitchJ * p%dt + p%torqM(2,2) = p%pitchJ + denom = p%pitchJ + p%pitchC*p%dt + p%pitchK*p%dt**2 + if (EqualRealNos(denom,0.0_BDKi)) then + call SetErrStat(ErrID_Fatal, "Cannot invert matrix for pitch actuator: J+c*dt+k*dt^2 is zero.", ErrStat, ErrMsg, RoutineName) + return + else + p%torqM(:,:) = p%torqM / denom + end if + end if !............................................... ! set parameters for File I/O data: @@ -2256,58 +2251,73 @@ SUBROUTINE BD_QuadraturePointDataAt0( p ) TYPE(BD_ParameterType), INTENT(INOUT) :: p !< Parameters - CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuadraturePointDataAt0' - INTEGER(IntKi) :: ErrStat2 ! The error status code - CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred + REAL(BDKi) :: rot0_temp(3) + REAL(BDKi) :: rotu_temp(3) + REAL(BDKi) :: rot_temp(3) + REAL(BDKi) :: R0_temp(3,3) + INTEGER(IntKi) :: nelem ! number of current element INTEGER(IntKi) :: idx_qp ! index of current quadrature point - INTEGER(IntKi) :: i - REAL(BDKi) :: twist, tan_vect(3), R0(3), u0(3) + INTEGER(IntKi) :: idx_node ! index of current GLL node - ! Loop through elements - DO nelem = 1,p%elem_total + CHARACTER(*), PARAMETER :: RoutineName = 'BD_QuadraturePointDataAt0' - ! Loop through quadrature points - do idx_qp = 1, p%nqp - ! Loop through displacement DOFs - do i = 1,3 + ! Initialize to zero for the summation + p%uu0(:,:,:) = 0.0_BDKi + p%rrN0(:,:,:) = 0.0_BDKi + p%E10(:,:,:) = 0.0_BDKi - ! Calculate the quadrature point initial positions by using the - ! shape functions to interpolate from the node initial positions - ! Initial displacement field \n - ! \f$ \underline{u_0}\left( \xi \right) = - ! \sum_{k=1}^{p+1} h^k\left( \xi \right) \underline{\hat{u}_0}^k - ! \f$ - u0(i) = dot_product(p%Shp(:,idx_qp), p%uuN0(i,:,nelem)) - ! Calculate \f$ x_0^\prime \f$, the derivative with respect to \f$ \hat{x} \f$-direction - ! (tangent to curve through this GLL point) - ! This uses the shape function derivative to calculate the tangent at the quadrature points - ! with respect to the element axis from the node positions. - ! Note: this is a unit vector after scaling by the Jacobian - tan_vect(i) = dot_product(p%ShpDer(:,idx_qp), p%uuN0(i,:,nelem)) / p%Jacobian(idx_qp,nelem) + ! calculate rrN0 (Initial relative rotation array) + DO nelem = 1,p%elem_total + p%rrN0(1:3,1,nelem) = (/ 0.0_BDKi, 0.0_BDKi, 0.0_BDKi /) ! first node has no rotation relative to itself. + DO idx_node=2,p%nodes_per_elem + ! Find resulting rotation parameters R(Nr) = Ri^T(Nu(1)) R(Nu(:)) + ! where R(Nu(1))^T is the transpose rotation parameters for the root node + CALL BD_CrvCompose(p%rrN0(1:3,idx_node,nelem),p%uuN0(4:6,1,nelem),p%uuN0(4:6,idx_node,nelem),FLAG_R1TR2) ! rrN0 = node composed with root + ENDDO + ENDDO - end do - ! Interpolate the twist to QP from the shape function and node values - twist = dot_product(p%Shp(:,idx_qp), p%twN0(:,nelem)) + DO nelem = 1,p%elem_total + DO idx_qp = 1,p%nqp + !> ### Calculate the the initial displacement fields in an element + !! Initial displacement field \n + !! \f$ \underline{u_0}\left( \xi \right) = + !! \sum_{k=1}^{p+1} h^k\left( \xi \right) \underline{\hat{u}_0}^k + !! \f$ \n + !! and curvature \n + !! \f$ \underline{c_0}\left( \xi \right) = + !! \sum_{k=1}^{p+1} h^k\left( \xi \right) \underline{\hat{c}_0}^k + !! \f$ - ! Calculate quadrature point initial rotation, R0 - ! The nodal rotation function is used to avoid errors that occur when - ! when interpolating the QP rotations from the node rotations. - call BD_ComputeIniNodalCrv(tan_vect, twist, R0, ErrStat2, ErrMsg2) + ! Note that p%uu0 was set to zero prior to this routine call, so the following is the summation. - ! Save initial position and rotation - p%uu0(1:3,idx_qp,nelem) = u0 - p%uu0(4:6,idx_qp,nelem) = R0 + DO idx_node=1,p%nodes_per_elem + p%uu0(1:3,idx_qp,nelem) = p%uu0(1:3,idx_qp,nelem) + p%Shp(idx_node,idx_qp)*p%uuN0(1:3,idx_node,nelem) + p%uu0(4:6,idx_qp,nelem) = p%uu0(4:6,idx_qp,nelem) + p%Shp(idx_node,idx_qp)*p%rrN0(1:3,idx_node,nelem) + ENDDO - ! Save initial tangent vector for calculating strain - p%E10(1:3,idx_qp,nelem) = tan_vect - end do + !> Add the blade root rotation parameters. That is, + !! compose the rotation parameters calculated with the shape functions with the rotation parameters + !! for the blade root. + rot0_temp(:) = p%uuN0(4:6,1,nelem) ! Rotation at root + rotu_temp(:) = p%uu0( 4:6,idx_qp,nelem) ! Rotation at current GLL point without root rotation + + CALL BD_CrvCompose(rot_temp,rot0_temp,rotu_temp,FLAG_R1R2) ! rot_temp = rot0_temp composed with rotu_temp + p%uu0(4:6,idx_qp,nelem) = rot_temp(:) ! Rotation parameters at current GLL point with the root orientation + + + !> Set the initial value of \f$ x_0^\prime \f$, the derivative with respect to \f$ \hat{x} \f$-direction + !! (tangent to curve through this GLL point). This is simply the + CALL BD_CrvMatrixR(p%uu0(4:6,idx_qp,nelem),R0_temp) ! returns R0_temp (the transpose of the DCM orientation matrix) + p%E10(:,idx_qp,nelem) = R0_temp(:,3) ! unit vector tangent to curve through this GLL point (derivative with respect to z in IEC coords). + ENDDO ENDDO + END SUBROUTINE BD_QuadraturePointDataAt0 @@ -2355,43 +2365,48 @@ SUBROUTINE BD_DisplacementQP( nelem, p, x, m ) TYPE(BD_ContinuousStateType), INTENT(IN ) :: x !< Continuous states at t TYPE(BD_MiscVarType), INTENT(INOUT) :: m !< misc/optimization variables - INTEGER(IntKi) :: node_start !< Node point of first node in current element - INTEGER(IntKi) :: node_end !< Node point of last node in current element - INTEGER(IntKi) :: i, idx_qp + INTEGER(IntKi) :: idx_qp !< index to the current quadrature point + INTEGER(IntKi) :: elem_start !< Node point of first node in current element + INTEGER(IntKi) :: idx_node CHARACTER(*), PARAMETER :: RoutineName = 'BD_DisplacementQP' - ! Node at start and end of element - node_start = p%node_elem_idx(nelem,1) - node_end = node_start + p%nodes_per_elem - 1 - - !> ### Calculate the the displacement fields in an element - !! Using equations (27) and (28) \n - !! \f$ \underline{u}\left( \xi \right) = - !! \sum_{i=1}^{p+1} h^i\left( \xi \right) \underline{\hat{u}}^i - !! \f$ \n - !! and \n - !! \f$ \underline{u}^\prime \left( \xi \right) = - !! \sum_{k=1}^{p+1} h^{k\prime} \left( \xi \right) \underline{\hat{u}}^i - !! \f$ - !! - !! | Variable | Value | - !! | :---------: | :------------------------------------------------------------------------- | - !! | \f$ \xi \f$ | Element natural coordinate \f$ \in [-1,1] \f$ | - !! | \f$ k \f$ | Node number of a \f$ p^\text{th} \f$ order Langrangian-interpolant | - !! | \f$ h^i \left( \xi \right ) \f$ | Component of the shape function matrix, \f$ \underline{\underline{N}} \f$ | - !! | \f$ h^{k\prime} \left( \xi \right ) \f$ | \f$ \frac{\mathrm{d}}{\mathrm{d}x_1} h^i \left( \xi \right) \f$ | - !! | \f$ \underline{\hat{u}}^i \f$ | \f$ k^\text{th} \f$ nodal value - - ! Loop through all quadrature points and displacement DOFs - ! dot_product appears to be more exact that matmul - forall (idx_qp = 1:p%nqp, i = 1:3) - m%qp%uuu(i,idx_qp,nelem) = dot_product(p%Shp(:,idx_qp), x%q(i,node_start:node_end)) - m%qp%uup(i,idx_qp,nelem) = dot_product(p%ShpDer(:,idx_qp), x%q(i,node_start:node_end)) / p%Jacobian(idx_qp,nelem) - end forall - - !> Calculate \f$ \underline{E}_1 = x_0^\prime + u^\prime \f$ (equation 23). Note E_1 is along the z direction. - m%qp%E1(1:3,:,nelem) = p%E10(1:3,:,nelem) + m%qp%uup(1:3,:,nelem) + DO idx_qp=1,p%nqp + ! Node point before start of this element + elem_start = p%node_elem_idx( nelem,1 ) + + + !> ### Calculate the the displacement fields in an element + !! Using equations (27) and (28) \n + !! \f$ \underline{u}\left( \xi \right) = + !! \sum_{i=1}^{p+1} h^i\left( \xi \right) \underline{\hat{u}}^i + !! \f$ \n + !! and \n + !! \f$ \underline{u}^\prime \left( \xi \right) = + !! \sum_{k=1}^{p+1} h^{k\prime} \left( \xi \right) \underline{\hat{u}}^i + !! \f$ + !! + !! | Variable | Value | + !! | :---------: | :------------------------------------------------------------------------- | + !! | \f$ \xi \f$ | Element natural coordinate \f$ \in [-1,1] \f$ | + !! | \f$ k \f$ | Node number of a \f$ p^\text{th} \f$ order Langrangian-interpolant | + !! | \f$ h^i \left( \xi \right ) \f$ | Component of the shape function matrix, \f$ \underline{\underline{N}} \f$ | + !! | \f$ h^{k\prime} \left( \xi \right ) \f$ | \f$ \frac{\mathrm{d}}{\mathrm{d}x_1} h^i \left( \xi \right) \f$ | + !! | \f$ \underline{\hat{u}}^i \f$ | \f$ k^\text{th} \f$ nodal value | + + ! Initialize values for summation + m%qp%uuu(:,idx_qp,nelem) = 0.0_BDKi ! displacement field \f$ \underline{u} \left( \xi \right) \f$ + m%qp%uup(:,idx_qp,nelem) = 0.0_BDKi ! displacement field \f$ \underline{u}^\prime \left( \xi \right) \f$ + + DO idx_node=1,p%nodes_per_elem + m%qp%uuu(1:3,idx_qp,nelem) = m%qp%uuu(1:3,idx_qp,nelem) + p%Shp(idx_node,idx_qp) *x%q(1:3,elem_start - 1 + idx_node) + m%qp%uup(1:3,idx_qp,nelem) = m%qp%uup(1:3,idx_qp,nelem) + p%ShpDer(idx_node,idx_qp)/p%Jacobian(idx_qp,nelem)*x%q(1:3,elem_start - 1 + idx_node) + ENDDO + + !> Calculate \f$ \underline{E}_1 = x_0^\prime + u^\prime \f$ (equation 23). Note E_1 is along the z direction. + m%qp%E1(1:3,idx_qp,nelem) = p%E10(1:3,idx_qp,nelem) + m%qp%uup(1:3,idx_qp,nelem) + + ENDDO END SUBROUTINE BD_DisplacementQP @@ -2742,6 +2757,8 @@ subroutine Calc_Fc_Fd() REAL(BDKi) :: e1s REAL(BDKi) :: eee(6) !< intermediate array for calculation Strain and curvature terms of Fc REAL(BDKi) :: fff(6) !< intermediate array for calculation of the elastic force, Fc + REAL(BDKi) :: R(3,3) !< rotation matrix at quatrature point + REAL(BDKi) :: Rx0p(3) !< \f$ \underline{R} \underline{x}^\prime_0 \f$ !REAL(BDKi) :: Wrk(3) @@ -2755,8 +2772,10 @@ subroutine Calc_Fc_Fd() !! !! Note: \f$ \underline{\underline{R}}\underline{\underline{R}}_0 \f$ is used to go from the material basis into the inertial basis !! and the transpose for the other direction. - eee(1:3) = m%qp%E1(1:3,idx_qp,nelem) - m%qp%RR0(1:3,3,idx_qp,nelem) ! Using RR0 z direction in IEC coords - + ! eee(1:3) = m%qp%E1(1:3,idx_qp,nelem) - m%qp%RR0(1:3,3,idx_qp,nelem) ! Using RR0 z direction in IEC coords + call BD_CrvMatrixR(m%qp%uuu(4:6,idx_qp,nelem), R) ! Get rotation at QP as a matrix + Rx0p = matmul(R,p%E10(:,idx_qp,nelem)) ! Calculate rotated initial tangent + eee(1:3) = m%qp%E1(1:3,idx_qp,nelem) - Rx0p ! Use rotated initial tangent in place of RR0*i1 to eliminate likely mismatch between R0*i1 and x0' !> ### Set the 1D sectional curvature, \f$ \underline{\kappa} \f$, equation (5) !! \f$ \underline{\kappa} = \underline{k} + \underline{\underline{R}}\underline{k}_i \f$ @@ -6035,7 +6054,8 @@ SUBROUTINE BD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM end if if (p%RotStates) then - RotateStates = matmul( u%RootMotion%Orientation(:,:,1), transpose( u%RootMotion%RefOrientation(:,:,1) ) ) + ! Calculate difference between input root orientation and root reference orientation + RotateStates = matmul( u%RootMotion%Orientation(:,:,1), OtherState%GlbRot ) do i=1,size(dXdu,1),3 dXdu(i:i+2, :) = matmul( RotateStates, dXdu(i:i+2, :) ) end do @@ -6131,7 +6151,8 @@ SUBROUTINE BD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, ErrStat, call SetErrStat(ErrStat2,ErrMsg2,ErrStat,ErrMsg,RoutineName) if (p%RotStates) then - RotateStates = matmul( u%RootMotion%Orientation(:,:,1), transpose( u%RootMotion%RefOrientation(:,:,1) ) ) + ! Calculate difference between input root orientation and root reference orientation + RotateStates = matmul( u%RootMotion%Orientation(:,:,1), OtherState%GlbRot ) RotateStatesTranspose = transpose( RotateStates ) if ( present(StateRotation) ) then diff --git a/modules/beamdyn/src/BeamDyn_Types.f90 b/modules/beamdyn/src/BeamDyn_Types.f90 index 1d3be92983..6980255649 100644 --- a/modules/beamdyn/src/BeamDyn_Types.f90 +++ b/modules/beamdyn/src/BeamDyn_Types.f90 @@ -162,8 +162,7 @@ MODULE BeamDyn_Types REAL(DbKi) :: dt = 0.0_R8Ki !< module dt [s] REAL(DbKi) , DIMENSION(1:9) :: coef = 0.0_R8Ki !< GA2 Coefficient [-] REAL(DbKi) :: rhoinf = 0.0_R8Ki !< Numerical Damping Coefficient for GA2 [-] - REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: uuN0 !< Initial Position Vector of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element) [-] - REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: twN0 !< Initial Twist of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: uuN0 !< Initial Postion Vector of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element) [-] REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Stif0_QP !< Sectional Stiffness Properties at quadrature points (6x6xqp) [-] REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: Mass0_QP !< Sectional Mass Properties at quadrature points (6x6xqp) [-] REAL(R8Ki) , DIMENSION(1:3) :: gravity = 0.0_R8Ki !< Gravitational acceleration -- intertial frame!!! [m/s^2] @@ -181,6 +180,7 @@ MODULE BeamDyn_Types REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: ShpDer !< Derivative of shape function matrix (index 1 = FE nodes; index 2=quadrature points) [-] REAL(R8Ki) , DIMENSION(:,:), ALLOCATABLE :: Jacobian !< Jacobian value at each quadrature point [-] REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: uu0 !< Initial Disp/Rot value at quadrature point (at T=0) [-] + REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: rrN0 !< Initial relative rotation array, relative to root (at T=0) (index 1=rot DOF; index 2=FE nodes; index 3=element) [-] REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: E10 !< Initial E10 at quadrature point [-] INTEGER(IntKi) :: nodes_per_elem = 0_IntKi !< Finite element (GLL) nodes per element [-] INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: node_elem_idx !< Index to first and last nodes of element in p%node_total sized arrays [-] @@ -1304,18 +1304,6 @@ subroutine BD_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) end if DstParamData%uuN0 = SrcParamData%uuN0 end if - if (allocated(SrcParamData%twN0)) then - LB(1:2) = lbound(SrcParamData%twN0, kind=B8Ki) - UB(1:2) = ubound(SrcParamData%twN0, kind=B8Ki) - if (.not. allocated(DstParamData%twN0)) then - allocate(DstParamData%twN0(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) - if (ErrStat2 /= 0) then - call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%twN0.', ErrStat, ErrMsg, RoutineName) - return - end if - end if - DstParamData%twN0 = SrcParamData%twN0 - end if if (allocated(SrcParamData%Stif0_QP)) then LB(1:3) = lbound(SrcParamData%Stif0_QP, kind=B8Ki) UB(1:3) = ubound(SrcParamData%Stif0_QP, kind=B8Ki) @@ -1443,6 +1431,18 @@ subroutine BD_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) end if DstParamData%uu0 = SrcParamData%uu0 end if + if (allocated(SrcParamData%rrN0)) then + LB(1:3) = lbound(SrcParamData%rrN0, kind=B8Ki) + UB(1:3) = ubound(SrcParamData%rrN0, kind=B8Ki) + if (.not. allocated(DstParamData%rrN0)) then + allocate(DstParamData%rrN0(LB(1):UB(1),LB(2):UB(2),LB(3):UB(3)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%rrN0.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%rrN0 = SrcParamData%rrN0 + end if if (allocated(SrcParamData%E10)) then LB(1:3) = lbound(SrcParamData%E10, kind=B8Ki) UB(1:3) = ubound(SrcParamData%E10, kind=B8Ki) @@ -1701,9 +1701,6 @@ subroutine BD_DestroyParam(ParamData, ErrStat, ErrMsg) if (allocated(ParamData%uuN0)) then deallocate(ParamData%uuN0) end if - if (allocated(ParamData%twN0)) then - deallocate(ParamData%twN0) - end if if (allocated(ParamData%Stif0_QP)) then deallocate(ParamData%Stif0_QP) end if @@ -1734,6 +1731,9 @@ subroutine BD_DestroyParam(ParamData, ErrStat, ErrMsg) if (allocated(ParamData%uu0)) then deallocate(ParamData%uu0) end if + if (allocated(ParamData%rrN0)) then + deallocate(ParamData%rrN0) + end if if (allocated(ParamData%E10)) then deallocate(ParamData%E10) end if @@ -1809,7 +1809,6 @@ subroutine BD_PackParam(RF, Indata) call RegPack(RF, InData%coef) call RegPack(RF, InData%rhoinf) call RegPackAlloc(RF, InData%uuN0) - call RegPackAlloc(RF, InData%twN0) call RegPackAlloc(RF, InData%Stif0_QP) call RegPackAlloc(RF, InData%Mass0_QP) call RegPack(RF, InData%gravity) @@ -1827,6 +1826,7 @@ subroutine BD_PackParam(RF, Indata) call RegPackAlloc(RF, InData%ShpDer) call RegPackAlloc(RF, InData%Jacobian) call RegPackAlloc(RF, InData%uu0) + call RegPackAlloc(RF, InData%rrN0) call RegPackAlloc(RF, InData%E10) call RegPack(RF, InData%nodes_per_elem) call RegPackAlloc(RF, InData%node_elem_idx) @@ -1915,7 +1915,6 @@ subroutine BD_UnPackParam(RF, OutData) call RegUnpack(RF, OutData%coef); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%rhoinf); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%uuN0); if (RegCheckErr(RF, RoutineName)) return - call RegUnpackAlloc(RF, OutData%twN0); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Stif0_QP); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Mass0_QP); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%gravity); if (RegCheckErr(RF, RoutineName)) return @@ -1933,6 +1932,7 @@ subroutine BD_UnPackParam(RF, OutData) call RegUnpackAlloc(RF, OutData%ShpDer); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%Jacobian); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%uu0); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%rrN0); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%E10); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%nodes_per_elem); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%node_elem_idx); if (RegCheckErr(RF, RoutineName)) return diff --git a/modules/beamdyn/src/Registry_BeamDyn.txt b/modules/beamdyn/src/Registry_BeamDyn.txt index 54037d8a73..448cd81abe 100644 --- a/modules/beamdyn/src/Registry_BeamDyn.txt +++ b/modules/beamdyn/src/Registry_BeamDyn.txt @@ -170,8 +170,7 @@ typedef ^ ParameterType DbKi coef {9} - - typedef ^ ParameterType DbKi rhoinf - - - "Numerical Damping Coefficient for GA2" #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv #the following are BDKi = R8Ki -typedef ^ ParameterType R8Ki uuN0 {:}{:}{:} - - "Initial Position Vector of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element)" - -typedef ^ ParameterType ^ twN0 {:}{:} - - "Initial Twist of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element)" - +typedef ^ ParameterType R8Ki uuN0 {:}{:}{:} - - "Initial Postion Vector of GLL (FE) nodes (index 1=DOF; index 2=FE nodes; index 3=element)" - typedef ^ ParameterType ^ Stif0_QP {:}{:}{:} - - "Sectional Stiffness Properties at quadrature points (6x6xqp)" - typedef ^ ParameterType ^ Mass0_QP {:}{:}{:} - - "Sectional Mass Properties at quadrature points (6x6xqp)" - typedef ^ ParameterType ^ gravity {3} - - "Gravitational acceleration -- intertial frame!!!" m/s^2 @@ -189,6 +188,7 @@ typedef ^ ParameterType ^ Shp {:}{:} - - typedef ^ ParameterType ^ ShpDer {:}{:} - - "Derivative of shape function matrix (index 1 = FE nodes; index 2=quadrature points)" - typedef ^ ParameterType ^ Jacobian {:}{:} - - "Jacobian value at each quadrature point" - typedef ^ ParameterType ^ uu0 {:}{:}{:} - - "Initial Disp/Rot value at quadrature point (at T=0)" - +typedef ^ ParameterType ^ rrN0 {:}{:}{:} - - "Initial relative rotation array, relative to root (at T=0) (index 1=rot DOF; index 2=FE nodes; index 3=element)" - typedef ^ ParameterType ^ E10 {:}{:}{:} - - "Initial E10 at quadrature point" - #end of BDKi-type variables #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/modules/beamdyn/tests/test_BD_QuadraturePointData.F90 b/modules/beamdyn/tests/test_BD_QuadraturePointData.F90 index 6101e47b92..fcf4f75a4f 100644 --- a/modules/beamdyn/tests/test_BD_QuadraturePointData.F90 +++ b/modules/beamdyn/tests/test_BD_QuadraturePointData.F90 @@ -27,6 +27,7 @@ module test_BD_QuadraturePointData real(BDKi), allocatable :: gll_nodes(:) real(BDKi), allocatable :: baseline_uu0(:,:,:) + real(BDKi), allocatable :: baseline_rrN0(:,:,:) real(BDKi), allocatable :: baseline_E10(:,:,:) real(BDKi), allocatable :: baseline_uuu(:,:,:) @@ -90,6 +91,7 @@ subroutine test_BD_QuadraturePointData_5node() call AllocAry(baseline_uu0 , p%dof_node, p%nqp, p%elem_total, 'baseline_uu0' , ErrStat, ErrMsg) call AllocAry(baseline_E10 , p%dof_node/2, p%nqp, p%elem_total, 'baseline_E10' , ErrStat, ErrMsg) + call AllocAry(baseline_rrN0 , p%dof_node/2, p%nodes_per_elem, p%elem_total, 'baseline_rrN0' , ErrStat, ErrMsg) call AllocAry(baseline_uuu , p%dof_node, p%nqp, p%elem_total, 'baseline_uuu' , ErrStat, ErrMsg) call AllocAry(baseline_uup , p%dof_node/2, p%nqp, p%elem_total, 'baseline_uup' , ErrStat, ErrMsg) @@ -102,10 +104,6 @@ subroutine test_BD_QuadraturePointData_5node() call AllocAry(baseline_Stif , 6, 6, p%nqp, p%elem_total, 'baseline_Stif' , ErrStat, ErrMsg) - ! Allocate memory for GLL node positions in 1D parametric space - call AllocAry(gll_nodes, nodes_per_elem, "GLL points array", ErrStat, ErrMsg) - gll_nodes = (/ -1., -0.6546536707079771, 0., 0.6546536707079771, 1. /) - ! assign baseline results ! uuN0 is of dimension (6 dof, nodes_per_elem, elem_total) @@ -125,19 +123,27 @@ subroutine test_BD_QuadraturePointData_5node() p%uuN0(1:3,5,1) = (/ -1., 1., 5. /) p%uuN0(4:6,5,1) = (/ -1.0730193445455083,-0.42803085368057275,1.292451050059679 /) + + ! the following is uuN0(4:6) with rotation of first node removed + baseline_rrN0(1:3,1,1) = (/ 0., 0., 0. /) + baseline_rrN0(1:3,2,1) = (/ -0.18695562365337798,-0.0032641497706398077,0.048935661676787534 /) + baseline_rrN0(1:3,3,1) = (/ -0.6080640291857297,-0.08595023366039768,0.4027112581652146 /) + baseline_rrN0(1:3,4,1) = (/ -1.1980591841054526,-0.3478409509012645,0.9658032687192992 /) + baseline_rrN0(1:3,5,1) = (/ -1.5856082606694464,-0.3853274394272689,1.3714709059387975 /) + ! We are just looking at one randomly selected point in the domain to test interpolation; can be expanded p%QptN(1) = 0.3 - ! Twist at nodes (nodes_per_elem, elem_total) - p%twN0(:,1) = 90.0*((gll_nodes+1)/2)**2 - ! Input baseline/reference quantities; uu0 and E10 are only for at quadrature points, so just 1 point here ! uu0 is reference line evaluated at quadrature point ! E10 is tangent evaluated at qudrature point baseline_uu0(1:3,1,1) = (/ 0.29298750000000007,-0.03250000000000007,3.2499999999999996 /) - baseline_uu0(4:6,1,1) = (/ -0.42032456079463276,-0.10798264336200536,0.61929246125947701 /) - baseline_E10(1:3,1,1) = (/ -0.21838554154630824,0.34664371674017153,0.91222030721097547 /) - + baseline_uu0(4:6,1,1) = (/ -0.419497643454797,-0.1153574679103733,0.610107968645409 /) + baseline_E10(1:3,1,1) = (/ -0.22332806017852783,0.3449485111415417,0.9116661133321399 /) + + ! Allocate memory for GLL node positions in 1D parametric space + call AllocAry(gll_nodes, nodes_per_elem, "GLL points array", ErrStat, ErrMsg) + gll_nodes = (/ -1., -0.6546536707079771, 0., 0.6546536707079771, 1. /) ! Build the shape functions and derivative of shape functions evaluated at QP points; this is tested elsewhere call BD_InitShpDerJaco(gll_nodes, p) @@ -145,6 +151,9 @@ subroutine test_BD_QuadraturePointData_5node() ! **** primary function being tested ***** call BD_QuadraturePointDataAt0( p ) + testname = "5 node, 1 element, 1 qp, curved: BD_DisplacementQPAt0: rrN0" + @assertEqual(baseline_rrN0(:,:,1), p%rrN0(:,:,1), tolerance, testname) + ! Test uu0; only one quadrature point for now testname = "5 node, 1 element, 1 qp, curved: BD_DisplacementQPAt0: uu0" do idx_qp = 1, p%nqp @@ -183,7 +192,7 @@ subroutine test_BD_QuadraturePointData_5node() baseline_uuu(1:3,idx_qp,nelem) = (/ 0.42250000000000015,-0.14787500000000003,0.4774250000000001 /) baseline_uuu(4:6,idx_qp,nelem) = (/ 0.042250000000000024,0.1300000000000001,0.02746250000000002 /) baseline_uup(1:3,idx_qp,nelem) = (/ 0.23717727987485349,-0.005929431996871376,0.2834268494504499 /) - baseline_E1(1:3, idx_qp,nelem) = (/ 0.018791738328546054, 0.34071428474330018, 1.1956471566614264 /) + baseline_E1(1:3, idx_qp,nelem) = (/ 0.01384921969632566, 0.33901907914467033, 1.1950929627825897 /) call BD_DisplacementQP( nelem, p, x, m ) @@ -205,9 +214,9 @@ subroutine test_BD_QuadraturePointData_5node() baseline_kappa(1:3,1,1) = (/ 0.024664714695954715,0.036297077098213545,0.02229356260962948 /) - baseline_RR0(1,1:3,1,nelem) = (/0.79124185715259476, -0.60219094249350502, -0.1063127098163618/) - baseline_RR0(2,1:3,1,nelem) = (/0.60261503127580685, 0.7383322551011402, 0.30285409879630898/) - baseline_RR0(3,1:3,1,nelem) = (/-0.10388189240754285, -0.30369647652886939, 0.94708869836662024/) + baseline_RR0(1,1:3,1,nelem) = (/0.7967507798136657,-0.5939809735620473,-0.11124206898740374/) + baseline_RR0(2,1:3,1,nelem) = (/0.5966254150993577,0.7439195402109748,0.3010346022466711 /) + baseline_RR0(3,1:3,1,nelem) = (/-0.09605367730511442,-0.30621939967705303,0.9471026186942948 /) CALL BD_RotationalInterpQP( nelem, p, x, m ) @@ -233,12 +242,12 @@ subroutine test_BD_QuadraturePointData_5node() enddo enddo ! the following should be the result from MATMUL(tempR6,MATMUL(p%Stif0_QP(1:6,1:6,temp_id2+idx_qp),TRANSPOSE(tempR6))) - baseline_Stif(1,1:6,idx_qp,nelem) = (/4.7536759583339689, -33.907248359179356, -19.542837968671446, 2.9365509821876983, -70.008981029110458, -31.39174980281188/) - baseline_Stif(2,1:6,idx_qp,nelem) = (/-19.401250769011185, 138.38617399872942, 79.760485041818299, -11.984990668437774, 285.72873055166156, 128.11963106880802/) - baseline_Stif(3,1:6,idx_qp,nelem) = (/-13.830884167369799, 98.653595365050748, 56.86015004293688, -8.5439345976052863, 203.69207236173781, 91.33471846615123/) - baseline_Stif(4,1:6,idx_qp,nelem) = (/3.141919298405611, -22.410832986789217, -12.916744914371989, 1.9408992709130821, -46.272099841270119, -20.748226294907653/) - baseline_Stif(5,1:6,idx_qp,nelem) = (/-51.422828167125537, 366.79122036858701, 211.40439684348502, -31.766102251101898, 757.32124637229549, 339.57984728541373/) - baseline_Stif(6,1:6,idx_qp,nelem) = (/-24.340652516975311, 173.61817619702015, 100.06686033300799, -15.036272493606024, 358.4729576086462, 160.73785435679258/) + baseline_Stif(1,1:6,idx_qp,nelem) = (/4.5918231909187375, -33.558422946165074, -19.41124878362651, 2.60126686515566, -69.25969416961556, -31.26026770547517 /) + baseline_Stif(2,1:6,idx_qp,nelem) = (/-18.923545538732206, 138.2989541247406, 79.99647091096304, -10.720184539884109, 285.4288856786646, 128.8279349796045 /) + baseline_Stif(3,1:6,idx_qp,nelem) = (/ -13.509458152867301, 98.7311774904666, 57.109222684340786, -7.65310518243836, 203.76676129761876, 91.96984745617996 /) + baseline_Stif(4,1:6,idx_qp,nelem) = (/ 2.852586665816869, -20.847560074045475, -12.058885358769254, 1.6159897420374438, -43.026325677681456, -19.419872917332995 /) + baseline_Stif(5,1:6,idx_qp,nelem) = (/-50.11731488891121, 366.27238899233606, 211.8634858589486, -28.39144827024861, 755.9328304872744, 341.18924335009 /) + baseline_Stif(6,1:6,idx_qp,nelem) = (/-23.86246662028767, 174.39407269994138, 100.87502434184734, -13.518082286573822, 359.9239499295936, 162.45117977068867 /) CALL BD_StifAtDeformedQP( nelem, p, m ) @@ -251,6 +260,9 @@ subroutine test_BD_QuadraturePointData_5node() if (allocated(gll_nodes)) deallocate(gll_nodes) if (allocated(baseline_uu0)) deallocate(baseline_uu0) if (allocated(baseline_E10)) deallocate(baseline_E10) + if (allocated(baseline_rrN0)) deallocate(baseline_rrN0) + if (allocated(baseline_rrN0)) deallocate(baseline_rrN0) + if (allocated(baseline_E10)) deallocate(baseline_E10) if (allocated(baseline_uuu)) deallocate(baseline_uuu) if (allocated(baseline_uup)) deallocate(baseline_uup) if (allocated(baseline_E1)) deallocate(baseline_E1) diff --git a/modules/beamdyn/tests/test_tools.F90 b/modules/beamdyn/tests/test_tools.F90 index b936d3bffa..1f64ec584e 100644 --- a/modules/beamdyn/tests/test_tools.F90 +++ b/modules/beamdyn/tests/test_tools.F90 @@ -132,10 +132,10 @@ type(BD_ParameterType) function simpleParameterType(elem_total, nodes_per_elem, call AllocAry(p%QPtw_ShpDer, p%nqp, p%nodes_per_elem, 'QPtw_ShpDer', ErrStat, ErrMsg) call AllocAry(p%Jacobian, p%nqp, p%elem_total, 'Jacobian', ErrStat, ErrMsg) call AllocAry(p%uuN0, p%dof_node, p%nodes_per_elem, p%elem_total,'uuN0', ErrStat, ErrMsg) - call AllocAry(p%twN0, p%nodes_per_elem, p%elem_total,'twN0', ErrStat, ErrMsg) call AllocAry(p%uu0, p%dof_node, p%nqp, p%elem_total,'uu0', ErrStat, ErrMsg) call AllocAry(p%E10, p%dof_node/2, p%nqp, p%elem_total,'E10', ErrStat, ErrMsg) + call AllocAry(p%rrN0, p%dof_node/2, p%nodes_per_elem, p%elem_total,'rrN0', ErrStat, ErrMsg) CALL AllocAry(p%node_elem_idx,p%elem_total,2,'start and end node numbers of elements in p%node_total sized arrays',ErrStat,ErrMsg) diff --git a/modules/elastodyn/src/ED_UserSubs.f90 b/modules/elastodyn/src/ED_UserSubs.f90 index de368c02eb..47e2abd8fd 100644 --- a/modules/elastodyn/src/ED_UserSubs.f90 +++ b/modules/elastodyn/src/ED_UserSubs.f90 @@ -101,6 +101,35 @@ SUBROUTINE UserTeet ( TeetDef, TeetRate, ZTime, DirRoot, TeetMom ) RETURN END SUBROUTINE UserTeet !======================================================================= +SUBROUTINE UserYawFrict ( ZTime, Fz, Mzz, Omg, OmgDot, DirRoot, YawFriMf ) + + ! This is a dummy routine for holding the place of a user-specified + ! Yaw Friction. Modify this code to create your own device. + + +USE Precision + + +IMPLICIT NONE + + + ! Passed Variables: +REAL(DbKi), INTENT(IN ) :: ZTime ! Current simulation time, sec. +REAL(R8Ki), INTENT(IN ) :: Fz, Mzz ! Yaw Bering normal force (positive if upward) and torque, N and N*m +REAL(R8Ki), INTENT(IN ) :: Omg ! Yaw rotational speed, rad/s. +REAL(R8Ki), INTENT(IN ) :: OmgDot ! Yaw rotational acceleration, rad/s^2. + +CHARACTER(1024), INTENT(IN ) :: DirRoot ! The name of the root file including the full path to the current working directory. This may be useful if you want this routine to write a permanent record of what it does to be stored with the simulation results: the results should be stored in a file whose name (including path) is generated by appending any suitable extension to DirRoot. + +REAL(ReKi), INTENT(OUT) :: YawFriMf ! Yaw friction moment, N*m. + + + +YawFriMf = 0.0 + +RETURN +END SUBROUTINE UserYawFrict +!======================================================================= SUBROUTINE UserTFrl ( TFrlDef, TFrlRate, ZTime, DirRoot, TFrlMom ) diff --git a/modules/elastodyn/src/ElastoDyn.f90 b/modules/elastodyn/src/ElastoDyn.f90 index 021eedaa85..4fc2f01560 100644 --- a/modules/elastodyn/src/ElastoDyn.f90 +++ b/modules/elastodyn/src/ElastoDyn.f90 @@ -1224,7 +1224,12 @@ SUBROUTINE ED_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) m%AllOuts( YawBrMzn) = DOT_PRODUCT( MomBNcRt, m%CoordSys%d2 ) m%AllOuts( YawBrMxp) = DOT_PRODUCT( MomBNcRt, m%CoordSys%b1 ) m%AllOuts( YawBrMyp) = -DOT_PRODUCT( MomBNcRt, m%CoordSys%b3 ) - + m%AllOuts(YawFriMom) = OtherState%Mfhat*0.001_ReKi !KBF add YawFricMom as an output based on HSSBrTq (kN-m) + m%AllOuts(YawFriMfp) = OtherState%YawFriMfp*0.001_ReKi + m%AllOuts(YawFriMz) = m%YawFriMz*0.001_ReKi + m%FrcONcRt = m%AllOuts( YawBrFzn)*1000_ReKi + m%AllOuts(OmegaYF) = OtherState%OmegaTn*R2D + m%AllOuts(dOmegaYF) = OtherState%OmegaDotTn*R2D ! Tower Base Loads: @@ -1956,6 +1961,9 @@ SUBROUTINE ED_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta INTEGER(IntKi) :: ErrStat2 ! The error status code CHARACTER(ErrMsgLen) :: ErrMsg2 ! The error message, if an error occurred CHARACTER(*), PARAMETER :: RoutineName = 'ED_CalcContStateDeriv' + Real(R8Ki) :: YawFriMz ! Loops through some or all of the DOFs. + Real(R8Ki) :: Fz ! Loops through some or all of the DOFs. + ! Initialize ErrStat @@ -1993,6 +2001,13 @@ SUBROUTINE ED_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, ErrSta CALL Teeter ( t, p, m%RtHS%TeetAng, m%RtHS%TeetAngVel, m%RtHS%TeetMom ) ! Compute moment from teeter springs and dampers, TeetMom; NOTE: TeetMom will be zero for a 3-blader since TeetAng = TeetAngVel = 0 CALL RFurling( t, p, x%QT(DOF_RFrl), x%QDT(DOF_RFrl), m%RtHS%RFrlMom ) ! Compute moment from rotor-furl springs and dampers, RFrlMom CALL TFurling( t, p, x%QT(DOF_TFrl), x%QDT(DOF_TFrl), m%RtHS%TFrlMom ) ! Compute moment from tail-furl springs and dampers, TFrlMom + ! Compute the yaw friction torque + Fz= m%FrcONcRt !YawBrFzn force from CalcOutput + YawFriMz=DOT_PRODUCT( m%RtHS%MomBNcRtt, m%CoordSys%d2 ) + u%YawMom + m%YawFriMz = YawFriMz + + CALL YawFriction( t, p, Fz, YawFriMz, OtherState%OmegaTn, OtherState%OmegaDotTn, m%RtHS%YawFriMom ) !Compute yaw Friction #RRD + !bjj: note m%RtHS%GBoxEffFac needed in OtherState only to fix HSSBrTrq (and used in FillAugMat) m%RtHS%GBoxEffFac = p%GBoxEff**OtherState%SgnPrvLSTQ ! = GBoxEff if SgnPrvLSTQ = 1 OR 1/GBoxEff if SgnPrvLSTQ = -1 @@ -3545,6 +3560,11 @@ SUBROUTINE SetPrimaryParameters( InitInp, p, InputFileData, ErrStat, ErrMsg ) p%TeetHSSp = 0.0 END IF + p%YawFrctMod = InputFileData%YawFrctMod + p%M_CD = InputFileData%M_CD + p%M_CSmax = InputFileData%M_CSmax + p%sig_v = InputFileData%sig_v + CALL AllocAry( p%TipMass, p%NumBl, 'TipMass', ErrStat, ErrMsg ) IF ( ErrStat >= AbortErrLev ) RETURN @@ -3908,6 +3928,10 @@ SUBROUTINE Init_MiscOtherStates( m, OtherState, p, x, InputFileData, ErrStat, Er OtherState%HSSBrTrqC = 0.0_ReKi OtherState%SgnPrvLSTQ = 1 OtherState%SgnLSTQ = 1 + OtherState%OmegaTn = 0.0_R8Ki + OtherState%OmegaDotTn = 0.0_R8Ki + OtherState%Mfhat = 0.0_ReKi + OtherState%YawFriMfp = 0.0_ReKi END SUBROUTINE Init_MiscOtherStates @@ -3925,393 +3949,400 @@ END SUBROUTINE Init_MiscOtherStates !! 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 25-Jan-2021 13:23:51. +!! This routine was generated by Write_ChckOutLst.m using the parameters listed in OutListParameters.xlsx. SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) !.................................................................................................................................. - + IMPLICIT NONE - + ! Passed variables - - CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list out user-requested outputs + + CHARACTER(ChanLen), INTENT(IN) :: OutList(:) !< The list of user-requested outputs TYPE(ED_ParameterType), INTENT(INOUT) :: p !< The module parameters INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status code CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if an error occurred - + ! Local variables - + INTEGER :: ErrStat2 ! temporary (local) error status INTEGER :: I ! Generic loop-counting index INTEGER :: J ! Generic loop-counting index INTEGER :: INDX ! Index for valid arrays INTEGER :: startIndx ! Index for using BeamDyn for Blades - - LOGICAL :: CheckOutListAgain ! Flag used to determine if output parameter starting with "M" is valid (or the negative of another parameter) LOGICAL :: InvalidOutput(0:MaxOutPts) ! This array determines if the output channel is valid for this configuration - CHARACTER(ChanLen) :: OutListTmp ! A string to temporarily hold OutList(I) CHARACTER(*), PARAMETER :: RoutineName = "SetOutParam" - - CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(1110) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically + + CHARACTER(OutStrLenM1), PARAMETER :: ValidParamAry(1115) = (/ & ! This lists the names of the allowed parameters, which must be sorted alphabetically "AZIMUTH ","BLDPITCH1 ","BLDPITCH2 ","BLDPITCH3 ","BLPITCH1 ","BLPITCH2 ","BLPITCH3 ", & - "GENACCEL ","GENSPEED ","HSSBRTQ ","HSSHFTA ","HSSHFTPWR ","HSSHFTTQ ","HSSHFTV ", & - "IPDEFL1 ","IPDEFL2 ","IPDEFL3 ","LSSGAGA ","LSSGAGAXA ","LSSGAGAXS ","LSSGAGFXA ", & - "LSSGAGFXS ","LSSGAGFYA ","LSSGAGFYS ","LSSGAGFZA ","LSSGAGFZS ","LSSGAGMXA ","LSSGAGMXS ", & - "LSSGAGMYA ","LSSGAGMYS ","LSSGAGMZA ","LSSGAGMZS ","LSSGAGP ","LSSGAGPXA ","LSSGAGPXS ", & - "LSSGAGV ","LSSGAGVXA ","LSSGAGVXS ","LSSHFTFXA ","LSSHFTFXS ","LSSHFTFYA ","LSSHFTFYS ", & - "LSSHFTFZA ","LSSHFTFZS ","LSSHFTMXA ","LSSHFTMXS ","LSSHFTPWR ","LSSHFTTQ ","LSSTIPA ", & - "LSSTIPAXA ","LSSTIPAXS ","LSSTIPMYA ","LSSTIPMYS ","LSSTIPMZA ","LSSTIPMZS ","LSSTIPP ", & - "LSSTIPPXA ","LSSTIPPXS ","LSSTIPV ","LSSTIPVXA ","LSSTIPVXS ","NACYAW ","NACYAWA ", & - "NACYAWP ","NACYAWV ","NCIMURAXS ","NCIMURAYS ","NCIMURAZS ","NCIMURVXS ","NCIMURVYS ", & - "NCIMURVZS ","NCIMUTAGXS","NCIMUTAGYS","NCIMUTAGZS","NCIMUTAXS ","NCIMUTAYS ","NCIMUTAZS ", & - "NCIMUTVXS ","NCIMUTVYS ","NCIMUTVZS ","OOPDEFL1 ","OOPDEFL2 ","OOPDEFL3 ","PTCHDEFL1 ", & - "PTCHDEFL2 ","PTCHDEFL3 ","PTCHPMZB1 ","PTCHPMZB2 ","PTCHPMZB3 ","PTCHPMZC1 ","PTCHPMZC2 ", & - "PTCHPMZC3 ","PTFMHEAVE ","PTFMPITCH ","PTFMRAXI ","PTFMRAXT ","PTFMRAYI ","PTFMRAYT ", & - "PTFMRAZI ","PTFMRAZT ","PTFMRDXI ","PTFMRDYI ","PTFMRDZI ","PTFMROLL ","PTFMRVXI ", & - "PTFMRVXT ","PTFMRVYI ","PTFMRVYT ","PTFMRVZI ","PTFMRVZT ","PTFMSURGE ","PTFMSWAY ", & - "PTFMTAGXI ","PTFMTAGXT ","PTFMTAGYI ","PTFMTAGYT ","PTFMTAGZI ","PTFMTAGZT ","PTFMTAXI ", & - "PTFMTAXT ","PTFMTAYI ","PTFMTAYT ","PTFMTAZI ","PTFMTAZT ","PTFMTDXI ","PTFMTDXT ", & - "PTFMTDYI ","PTFMTDYT ","PTFMTDZI ","PTFMTDZT ","PTFMTVXI ","PTFMTVXT ","PTFMTVYI ", & - "PTFMTVYT ","PTFMTVZI ","PTFMTVZT ","PTFMYAW ","QD2_B1E1 ","QD2_B1F1 ","QD2_B1F2 ", & - "QD2_B2E1 ","QD2_B2F1 ","QD2_B2F2 ","QD2_B3E1 ","QD2_B3F1 ","QD2_B3F2 ","QD2_DRTR ", & - "QD2_GEAZ ","QD2_HV ","QD2_P ","QD2_R ","QD2_RFRL ","QD2_SG ","QD2_SW ", & - "QD2_TEET ","QD2_TFA1 ","QD2_TFA2 ","QD2_TFRL ","QD2_TSS1 ","QD2_TSS2 ","QD2_Y ", & - "QD2_YAW ","QD_B1E1 ","QD_B1F1 ","QD_B1F2 ","QD_B2E1 ","QD_B2F1 ","QD_B2F2 ", & - "QD_B3E1 ","QD_B3F1 ","QD_B3F2 ","QD_DRTR ","QD_GEAZ ","QD_HV ","QD_P ", & - "QD_R ","QD_RFRL ","QD_SG ","QD_SW ","QD_TEET ","QD_TFA1 ","QD_TFA2 ", & - "QD_TFRL ","QD_TSS1 ","QD_TSS2 ","QD_Y ","QD_YAW ","Q_B1E1 ","Q_B1F1 ", & - "Q_B1F2 ","Q_B2E1 ","Q_B2F1 ","Q_B2F2 ","Q_B3E1 ","Q_B3F1 ","Q_B3F2 ", & - "Q_DRTR ","Q_GEAZ ","Q_HV ","Q_P ","Q_R ","Q_RFRL ","Q_SG ", & - "Q_SW ","Q_TEET ","Q_TFA1 ","Q_TFA2 ","Q_TFRL ","Q_TSS1 ","Q_TSS2 ", & - "Q_Y ","Q_YAW ","RFRLBRM ","ROLLDEFL1 ","ROLLDEFL2 ","ROLLDEFL3 ","ROOTFXB1 ", & - "ROOTFXB2 ","ROOTFXB3 ","ROOTFXC1 ","ROOTFXC2 ","ROOTFXC3 ","ROOTFYB1 ","ROOTFYB2 ", & - "ROOTFYB3 ","ROOTFYC1 ","ROOTFYC2 ","ROOTFYC3 ","ROOTFZB1 ","ROOTFZB2 ","ROOTFZB3 ", & - "ROOTFZC1 ","ROOTFZC2 ","ROOTFZC3 ","ROOTMEDG1 ","ROOTMEDG2 ","ROOTMEDG3 ","ROOTMFLP1 ", & - "ROOTMFLP2 ","ROOTMFLP3 ","ROOTMIP1 ","ROOTMIP2 ","ROOTMIP3 ","ROOTMOOP1 ","ROOTMOOP2 ", & - "ROOTMOOP3 ","ROOTMXB1 ","ROOTMXB2 ","ROOTMXB3 ","ROOTMXC1 ","ROOTMXC2 ","ROOTMXC3 ", & - "ROOTMYB1 ","ROOTMYB2 ","ROOTMYB3 ","ROOTMYC1 ","ROOTMYC2 ","ROOTMYC3 ","ROOTMZB1 ", & - "ROOTMZB2 ","ROOTMZB3 ","ROOTMZC1 ","ROOTMZC2 ","ROOTMZC3 ","ROTACCEL ","ROTFURL ", & - "ROTFURLA ","ROTFURLP ","ROTFURLV ","ROTPWR ","ROTSPEED ","ROTTEETA ","ROTTEETP ", & - "ROTTEETV ","ROTTHRUST ","ROTTORQ ","SPN1ALGXB1","SPN1ALGXB2","SPN1ALGXB3","SPN1ALGYB1", & - "SPN1ALGYB2","SPN1ALGYB3","SPN1ALGZB1","SPN1ALGZB2","SPN1ALGZB3","SPN1ALXB1 ","SPN1ALXB2 ", & - "SPN1ALXB3 ","SPN1ALYB1 ","SPN1ALYB2 ","SPN1ALYB3 ","SPN1ALZB1 ","SPN1ALZB2 ","SPN1ALZB3 ", & - "SPN1FLXB1 ","SPN1FLXB2 ","SPN1FLXB3 ","SPN1FLYB1 ","SPN1FLYB2 ","SPN1FLYB3 ","SPN1FLZB1 ", & - "SPN1FLZB2 ","SPN1FLZB3 ","SPN1MLXB1 ","SPN1MLXB2 ","SPN1MLXB3 ","SPN1MLYB1 ","SPN1MLYB2 ", & - "SPN1MLYB3 ","SPN1MLZB1 ","SPN1MLZB2 ","SPN1MLZB3 ","SPN1RDXB1 ","SPN1RDXB2 ","SPN1RDXB3 ", & - "SPN1RDYB1 ","SPN1RDYB2 ","SPN1RDYB3 ","SPN1RDZB1 ","SPN1RDZB2 ","SPN1RDZB3 ","SPN1TDXB1 ", & - "SPN1TDXB2 ","SPN1TDXB3 ","SPN1TDYB1 ","SPN1TDYB2 ","SPN1TDYB3 ","SPN1TDZB1 ","SPN1TDZB2 ", & - "SPN1TDZB3 ","SPN2ALGXB1","SPN2ALGXB2","SPN2ALGXB3","SPN2ALGYB1","SPN2ALGYB2","SPN2ALGYB3", & - "SPN2ALGZB1","SPN2ALGZB2","SPN2ALGZB3","SPN2ALXB1 ","SPN2ALXB2 ","SPN2ALXB3 ","SPN2ALYB1 ", & - "SPN2ALYB2 ","SPN2ALYB3 ","SPN2ALZB1 ","SPN2ALZB2 ","SPN2ALZB3 ","SPN2FLXB1 ","SPN2FLXB2 ", & - "SPN2FLXB3 ","SPN2FLYB1 ","SPN2FLYB2 ","SPN2FLYB3 ","SPN2FLZB1 ","SPN2FLZB2 ","SPN2FLZB3 ", & - "SPN2MLXB1 ","SPN2MLXB2 ","SPN2MLXB3 ","SPN2MLYB1 ","SPN2MLYB2 ","SPN2MLYB3 ","SPN2MLZB1 ", & - "SPN2MLZB2 ","SPN2MLZB3 ","SPN2RDXB1 ","SPN2RDXB2 ","SPN2RDXB3 ","SPN2RDYB1 ","SPN2RDYB2 ", & - "SPN2RDYB3 ","SPN2RDZB1 ","SPN2RDZB2 ","SPN2RDZB3 ","SPN2TDXB1 ","SPN2TDXB2 ","SPN2TDXB3 ", & - "SPN2TDYB1 ","SPN2TDYB2 ","SPN2TDYB3 ","SPN2TDZB1 ","SPN2TDZB2 ","SPN2TDZB3 ","SPN3ALGXB1", & - "SPN3ALGXB2","SPN3ALGXB3","SPN3ALGYB1","SPN3ALGYB2","SPN3ALGYB3","SPN3ALGZB1","SPN3ALGZB2", & - "SPN3ALGZB3","SPN3ALXB1 ","SPN3ALXB2 ","SPN3ALXB3 ","SPN3ALYB1 ","SPN3ALYB2 ","SPN3ALYB3 ", & - "SPN3ALZB1 ","SPN3ALZB2 ","SPN3ALZB3 ","SPN3FLXB1 ","SPN3FLXB2 ","SPN3FLXB3 ","SPN3FLYB1 ", & - "SPN3FLYB2 ","SPN3FLYB3 ","SPN3FLZB1 ","SPN3FLZB2 ","SPN3FLZB3 ","SPN3MLXB1 ","SPN3MLXB2 ", & - "SPN3MLXB3 ","SPN3MLYB1 ","SPN3MLYB2 ","SPN3MLYB3 ","SPN3MLZB1 ","SPN3MLZB2 ","SPN3MLZB3 ", & - "SPN3RDXB1 ","SPN3RDXB2 ","SPN3RDXB3 ","SPN3RDYB1 ","SPN3RDYB2 ","SPN3RDYB3 ","SPN3RDZB1 ", & - "SPN3RDZB2 ","SPN3RDZB3 ","SPN3TDXB1 ","SPN3TDXB2 ","SPN3TDXB3 ","SPN3TDYB1 ","SPN3TDYB2 ", & - "SPN3TDYB3 ","SPN3TDZB1 ","SPN3TDZB2 ","SPN3TDZB3 ","SPN4ALGXB1","SPN4ALGXB2","SPN4ALGXB3", & - "SPN4ALGYB1","SPN4ALGYB2","SPN4ALGYB3","SPN4ALGZB1","SPN4ALGZB2","SPN4ALGZB3","SPN4ALXB1 ", & - "SPN4ALXB2 ","SPN4ALXB3 ","SPN4ALYB1 ","SPN4ALYB2 ","SPN4ALYB3 ","SPN4ALZB1 ","SPN4ALZB2 ", & - "SPN4ALZB3 ","SPN4FLXB1 ","SPN4FLXB2 ","SPN4FLXB3 ","SPN4FLYB1 ","SPN4FLYB2 ","SPN4FLYB3 ", & - "SPN4FLZB1 ","SPN4FLZB2 ","SPN4FLZB3 ","SPN4MLXB1 ","SPN4MLXB2 ","SPN4MLXB3 ","SPN4MLYB1 ", & - "SPN4MLYB2 ","SPN4MLYB3 ","SPN4MLZB1 ","SPN4MLZB2 ","SPN4MLZB3 ","SPN4RDXB1 ","SPN4RDXB2 ", & - "SPN4RDXB3 ","SPN4RDYB1 ","SPN4RDYB2 ","SPN4RDYB3 ","SPN4RDZB1 ","SPN4RDZB2 ","SPN4RDZB3 ", & - "SPN4TDXB1 ","SPN4TDXB2 ","SPN4TDXB3 ","SPN4TDYB1 ","SPN4TDYB2 ","SPN4TDYB3 ","SPN4TDZB1 ", & - "SPN4TDZB2 ","SPN4TDZB3 ","SPN5ALGXB1","SPN5ALGXB2","SPN5ALGXB3","SPN5ALGYB1","SPN5ALGYB2", & - "SPN5ALGYB3","SPN5ALGZB1","SPN5ALGZB2","SPN5ALGZB3","SPN5ALXB1 ","SPN5ALXB2 ","SPN5ALXB3 ", & - "SPN5ALYB1 ","SPN5ALYB2 ","SPN5ALYB3 ","SPN5ALZB1 ","SPN5ALZB2 ","SPN5ALZB3 ","SPN5FLXB1 ", & - "SPN5FLXB2 ","SPN5FLXB3 ","SPN5FLYB1 ","SPN5FLYB2 ","SPN5FLYB3 ","SPN5FLZB1 ","SPN5FLZB2 ", & - "SPN5FLZB3 ","SPN5MLXB1 ","SPN5MLXB2 ","SPN5MLXB3 ","SPN5MLYB1 ","SPN5MLYB2 ","SPN5MLYB3 ", & - "SPN5MLZB1 ","SPN5MLZB2 ","SPN5MLZB3 ","SPN5RDXB1 ","SPN5RDXB2 ","SPN5RDXB3 ","SPN5RDYB1 ", & - "SPN5RDYB2 ","SPN5RDYB3 ","SPN5RDZB1 ","SPN5RDZB2 ","SPN5RDZB3 ","SPN5TDXB1 ","SPN5TDXB2 ", & - "SPN5TDXB3 ","SPN5TDYB1 ","SPN5TDYB2 ","SPN5TDYB3 ","SPN5TDZB1 ","SPN5TDZB2 ","SPN5TDZB3 ", & - "SPN6ALGXB1","SPN6ALGXB2","SPN6ALGXB3","SPN6ALGYB1","SPN6ALGYB2","SPN6ALGYB3","SPN6ALGZB1", & - "SPN6ALGZB2","SPN6ALGZB3","SPN6ALXB1 ","SPN6ALXB2 ","SPN6ALXB3 ","SPN6ALYB1 ","SPN6ALYB2 ", & - "SPN6ALYB3 ","SPN6ALZB1 ","SPN6ALZB2 ","SPN6ALZB3 ","SPN6FLXB1 ","SPN6FLXB2 ","SPN6FLXB3 ", & - "SPN6FLYB1 ","SPN6FLYB2 ","SPN6FLYB3 ","SPN6FLZB1 ","SPN6FLZB2 ","SPN6FLZB3 ","SPN6MLXB1 ", & - "SPN6MLXB2 ","SPN6MLXB3 ","SPN6MLYB1 ","SPN6MLYB2 ","SPN6MLYB3 ","SPN6MLZB1 ","SPN6MLZB2 ", & - "SPN6MLZB3 ","SPN6RDXB1 ","SPN6RDXB2 ","SPN6RDXB3 ","SPN6RDYB1 ","SPN6RDYB2 ","SPN6RDYB3 ", & - "SPN6RDZB1 ","SPN6RDZB2 ","SPN6RDZB3 ","SPN6TDXB1 ","SPN6TDXB2 ","SPN6TDXB3 ","SPN6TDYB1 ", & - "SPN6TDYB2 ","SPN6TDYB3 ","SPN6TDZB1 ","SPN6TDZB2 ","SPN6TDZB3 ","SPN7ALGXB1","SPN7ALGXB2", & - "SPN7ALGXB3","SPN7ALGYB1","SPN7ALGYB2","SPN7ALGYB3","SPN7ALGZB1","SPN7ALGZB2","SPN7ALGZB3", & - "SPN7ALXB1 ","SPN7ALXB2 ","SPN7ALXB3 ","SPN7ALYB1 ","SPN7ALYB2 ","SPN7ALYB3 ","SPN7ALZB1 ", & - "SPN7ALZB2 ","SPN7ALZB3 ","SPN7FLXB1 ","SPN7FLXB2 ","SPN7FLXB3 ","SPN7FLYB1 ","SPN7FLYB2 ", & - "SPN7FLYB3 ","SPN7FLZB1 ","SPN7FLZB2 ","SPN7FLZB3 ","SPN7MLXB1 ","SPN7MLXB2 ","SPN7MLXB3 ", & - "SPN7MLYB1 ","SPN7MLYB2 ","SPN7MLYB3 ","SPN7MLZB1 ","SPN7MLZB2 ","SPN7MLZB3 ","SPN7RDXB1 ", & - "SPN7RDXB2 ","SPN7RDXB3 ","SPN7RDYB1 ","SPN7RDYB2 ","SPN7RDYB3 ","SPN7RDZB1 ","SPN7RDZB2 ", & - "SPN7RDZB3 ","SPN7TDXB1 ","SPN7TDXB2 ","SPN7TDXB3 ","SPN7TDYB1 ","SPN7TDYB2 ","SPN7TDYB3 ", & - "SPN7TDZB1 ","SPN7TDZB2 ","SPN7TDZB3 ","SPN8ALGXB1","SPN8ALGXB2","SPN8ALGXB3","SPN8ALGYB1", & - "SPN8ALGYB2","SPN8ALGYB3","SPN8ALGZB1","SPN8ALGZB2","SPN8ALGZB3","SPN8ALXB1 ","SPN8ALXB2 ", & - "SPN8ALXB3 ","SPN8ALYB1 ","SPN8ALYB2 ","SPN8ALYB3 ","SPN8ALZB1 ","SPN8ALZB2 ","SPN8ALZB3 ", & - "SPN8FLXB1 ","SPN8FLXB2 ","SPN8FLXB3 ","SPN8FLYB1 ","SPN8FLYB2 ","SPN8FLYB3 ","SPN8FLZB1 ", & - "SPN8FLZB2 ","SPN8FLZB3 ","SPN8MLXB1 ","SPN8MLXB2 ","SPN8MLXB3 ","SPN8MLYB1 ","SPN8MLYB2 ", & - "SPN8MLYB3 ","SPN8MLZB1 ","SPN8MLZB2 ","SPN8MLZB3 ","SPN8RDXB1 ","SPN8RDXB2 ","SPN8RDXB3 ", & - "SPN8RDYB1 ","SPN8RDYB2 ","SPN8RDYB3 ","SPN8RDZB1 ","SPN8RDZB2 ","SPN8RDZB3 ","SPN8TDXB1 ", & - "SPN8TDXB2 ","SPN8TDXB3 ","SPN8TDYB1 ","SPN8TDYB2 ","SPN8TDYB3 ","SPN8TDZB1 ","SPN8TDZB2 ", & - "SPN8TDZB3 ","SPN9ALGXB1","SPN9ALGXB2","SPN9ALGXB3","SPN9ALGYB1","SPN9ALGYB2","SPN9ALGYB3", & - "SPN9ALGZB1","SPN9ALGZB2","SPN9ALGZB3","SPN9ALXB1 ","SPN9ALXB2 ","SPN9ALXB3 ","SPN9ALYB1 ", & - "SPN9ALYB2 ","SPN9ALYB3 ","SPN9ALZB1 ","SPN9ALZB2 ","SPN9ALZB3 ","SPN9FLXB1 ","SPN9FLXB2 ", & - "SPN9FLXB3 ","SPN9FLYB1 ","SPN9FLYB2 ","SPN9FLYB3 ","SPN9FLZB1 ","SPN9FLZB2 ","SPN9FLZB3 ", & - "SPN9MLXB1 ","SPN9MLXB2 ","SPN9MLXB3 ","SPN9MLYB1 ","SPN9MLYB2 ","SPN9MLYB3 ","SPN9MLZB1 ", & - "SPN9MLZB2 ","SPN9MLZB3 ","SPN9RDXB1 ","SPN9RDXB2 ","SPN9RDXB3 ","SPN9RDYB1 ","SPN9RDYB2 ", & - "SPN9RDYB3 ","SPN9RDZB1 ","SPN9RDZB2 ","SPN9RDZB3 ","SPN9TDXB1 ","SPN9TDXB2 ","SPN9TDXB3 ", & - "SPN9TDYB1 ","SPN9TDYB2 ","SPN9TDYB3 ","SPN9TDZB1 ","SPN9TDZB2 ","SPN9TDZB3 ","TAILFURL ", & - "TAILFURLA ","TAILFURLP ","TAILFURLV ","TEETAYA ","TEETDEFL ","TEETPYA ","TEETVYA ", & - "TFRLBRM ","TIP2TWR1 ","TIP2TWR2 ","TIP2TWR3 ","TIPALGXB1 ","TIPALGXB2 ","TIPALGXB3 ", & - "TIPALGYB1 ","TIPALGYB2 ","TIPALGYB3 ","TIPALGZB1 ","TIPALGZB2 ","TIPALGZB3 ","TIPALXB1 ", & - "TIPALXB2 ","TIPALXB3 ","TIPALYB1 ","TIPALYB2 ","TIPALYB3 ","TIPALZB1 ","TIPALZB2 ", & - "TIPALZB3 ","TIPCLRNC1 ","TIPCLRNC2 ","TIPCLRNC3 ","TIPDXB1 ","TIPDXB2 ","TIPDXB3 ", & - "TIPDXC1 ","TIPDXC2 ","TIPDXC3 ","TIPDYB1 ","TIPDYB2 ","TIPDYB3 ","TIPDYC1 ", & - "TIPDYC2 ","TIPDYC3 ","TIPDZB1 ","TIPDZB2 ","TIPDZB3 ","TIPDZC1 ","TIPDZC2 ", & - "TIPDZC3 ","TIPRDXB1 ","TIPRDXB2 ","TIPRDXB3 ","TIPRDYB1 ","TIPRDYB2 ","TIPRDYB3 ", & - "TIPRDZB1 ","TIPRDZB2 ","TIPRDZB3 ","TIPRDZC1 ","TIPRDZC2 ","TIPRDZC3 ","TTDSPAX ", & - "TTDSPFA ","TTDSPPTCH ","TTDSPROLL ","TTDSPSS ","TTDSPTWST ","TWHT1ALGXT","TWHT1ALGYT", & - "TWHT1ALGZT","TWHT1ALXT ","TWHT1ALYT ","TWHT1ALZT ","TWHT1FLXT ","TWHT1FLYT ","TWHT1FLZT ", & - "TWHT1MLXT ","TWHT1MLYT ","TWHT1MLZT ","TWHT1RDXT ","TWHT1RDYT ","TWHT1RDZT ","TWHT1RPXI ", & - "TWHT1RPYI ","TWHT1RPZI ","TWHT1TDXT ","TWHT1TDYT ","TWHT1TDZT ","TWHT1TPXI ","TWHT1TPYI ", & - "TWHT1TPZI ","TWHT2ALGXT","TWHT2ALGYT","TWHT2ALGZT","TWHT2ALXT ","TWHT2ALYT ","TWHT2ALZT ", & - "TWHT2FLXT ","TWHT2FLYT ","TWHT2FLZT ","TWHT2MLXT ","TWHT2MLYT ","TWHT2MLZT ","TWHT2RDXT ", & - "TWHT2RDYT ","TWHT2RDZT ","TWHT2RPXI ","TWHT2RPYI ","TWHT2RPZI ","TWHT2TDXT ","TWHT2TDYT ", & - "TWHT2TDZT ","TWHT2TPXI ","TWHT2TPYI ","TWHT2TPZI ","TWHT3ALGXT","TWHT3ALGYT","TWHT3ALGZT", & - "TWHT3ALXT ","TWHT3ALYT ","TWHT3ALZT ","TWHT3FLXT ","TWHT3FLYT ","TWHT3FLZT ","TWHT3MLXT ", & - "TWHT3MLYT ","TWHT3MLZT ","TWHT3RDXT ","TWHT3RDYT ","TWHT3RDZT ","TWHT3RPXI ","TWHT3RPYI ", & - "TWHT3RPZI ","TWHT3TDXT ","TWHT3TDYT ","TWHT3TDZT ","TWHT3TPXI ","TWHT3TPYI ","TWHT3TPZI ", & - "TWHT4ALGXT","TWHT4ALGYT","TWHT4ALGZT","TWHT4ALXT ","TWHT4ALYT ","TWHT4ALZT ","TWHT4FLXT ", & - "TWHT4FLYT ","TWHT4FLZT ","TWHT4MLXT ","TWHT4MLYT ","TWHT4MLZT ","TWHT4RDXT ","TWHT4RDYT ", & - "TWHT4RDZT ","TWHT4RPXI ","TWHT4RPYI ","TWHT4RPZI ","TWHT4TDXT ","TWHT4TDYT ","TWHT4TDZT ", & - "TWHT4TPXI ","TWHT4TPYI ","TWHT4TPZI ","TWHT5ALGXT","TWHT5ALGYT","TWHT5ALGZT","TWHT5ALXT ", & - "TWHT5ALYT ","TWHT5ALZT ","TWHT5FLXT ","TWHT5FLYT ","TWHT5FLZT ","TWHT5MLXT ","TWHT5MLYT ", & - "TWHT5MLZT ","TWHT5RDXT ","TWHT5RDYT ","TWHT5RDZT ","TWHT5RPXI ","TWHT5RPYI ","TWHT5RPZI ", & - "TWHT5TDXT ","TWHT5TDYT ","TWHT5TDZT ","TWHT5TPXI ","TWHT5TPYI ","TWHT5TPZI ","TWHT6ALGXT", & - "TWHT6ALGYT","TWHT6ALGZT","TWHT6ALXT ","TWHT6ALYT ","TWHT6ALZT ","TWHT6FLXT ","TWHT6FLYT ", & - "TWHT6FLZT ","TWHT6MLXT ","TWHT6MLYT ","TWHT6MLZT ","TWHT6RDXT ","TWHT6RDYT ","TWHT6RDZT ", & - "TWHT6RPXI ","TWHT6RPYI ","TWHT6RPZI ","TWHT6TDXT ","TWHT6TDYT ","TWHT6TDZT ","TWHT6TPXI ", & - "TWHT6TPYI ","TWHT6TPZI ","TWHT7ALGXT","TWHT7ALGYT","TWHT7ALGZT","TWHT7ALXT ","TWHT7ALYT ", & - "TWHT7ALZT ","TWHT7FLXT ","TWHT7FLYT ","TWHT7FLZT ","TWHT7MLXT ","TWHT7MLYT ","TWHT7MLZT ", & - "TWHT7RDXT ","TWHT7RDYT ","TWHT7RDZT ","TWHT7RPXI ","TWHT7RPYI ","TWHT7RPZI ","TWHT7TDXT ", & - "TWHT7TDYT ","TWHT7TDZT ","TWHT7TPXI ","TWHT7TPYI ","TWHT7TPZI ","TWHT8ALGXT","TWHT8ALGYT", & - "TWHT8ALGZT","TWHT8ALXT ","TWHT8ALYT ","TWHT8ALZT ","TWHT8FLXT ","TWHT8FLYT ","TWHT8FLZT ", & - "TWHT8MLXT ","TWHT8MLYT ","TWHT8MLZT ","TWHT8RDXT ","TWHT8RDYT ","TWHT8RDZT ","TWHT8RPXI ", & - "TWHT8RPYI ","TWHT8RPZI ","TWHT8TDXT ","TWHT8TDYT ","TWHT8TDZT ","TWHT8TPXI ","TWHT8TPYI ", & - "TWHT8TPZI ","TWHT9ALGXT","TWHT9ALGYT","TWHT9ALGZT","TWHT9ALXT ","TWHT9ALYT ","TWHT9ALZT ", & - "TWHT9FLXT ","TWHT9FLYT ","TWHT9FLZT ","TWHT9MLXT ","TWHT9MLYT ","TWHT9MLZT ","TWHT9RDXT ", & - "TWHT9RDYT ","TWHT9RDZT ","TWHT9RPXI ","TWHT9RPYI ","TWHT9RPZI ","TWHT9TDXT ","TWHT9TDYT ", & - "TWHT9TDZT ","TWHT9TPXI ","TWHT9TPYI ","TWHT9TPZI ","TWRBSFXT ","TWRBSFYT ","TWRBSFZT ", & - "TWRBSMXT ","TWRBSMYT ","TWRBSMZT ","TWRCLRNC1 ","TWRCLRNC2 ","TWRCLRNC3 ","TWRTPTDXI ", & - "TWRTPTDYI ","TWRTPTDZI ","TWSTDEFL1 ","TWSTDEFL2 ","TWSTDEFL3 ","YAWACCEL ","YAWAZN ", & - "YAWAZP ","YAWBRFXN ","YAWBRFXP ","YAWBRFYN ","YAWBRFYP ","YAWBRFZN ","YAWBRFZP ", & - "YAWBRMXN ","YAWBRMXP ","YAWBRMYN ","YAWBRMYP ","YAWBRMZN ","YAWBRMZP ","YAWBRRAXP ", & - "YAWBRRAYP ","YAWBRRAZP ","YAWBRRDXT ","YAWBRRDYT ","YAWBRRDZT ","YAWBRRVXP ","YAWBRRVYP ", & - "YAWBRRVZP ","YAWBRTAGXP","YAWBRTAGYP","YAWBRTAGZP","YAWBRTAXP ","YAWBRTAYP ","YAWBRTAZP ", & - "YAWBRTDXI ","YAWBRTDXP ","YAWBRTDXT ","YAWBRTDYI ","YAWBRTDYP ","YAWBRTDYT ","YAWBRTDZI ", & - "YAWBRTDZP ","YAWBRTDZT ","YAWBRTVXP ","YAWBRTVYP ","YAWBRTVZP ","YAWPOS ","YAWPZN ", & - "YAWPZP ","YAWRATE ","YAWVZN ","YAWVZP "/) - INTEGER(IntKi), PARAMETER :: ParamIndxAry(1110) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) + "DOMEGAYF ","GENACCEL ","GENSPEED ","HSSBRTQ ","HSSHFTA ","HSSHFTPWR ","HSSHFTTQ ", & + "HSSHFTV ","IPDEFL1 ","IPDEFL2 ","IPDEFL3 ","LSSGAGA ","LSSGAGAXA ","LSSGAGAXS ", & + "LSSGAGFXA ","LSSGAGFXS ","LSSGAGFYA ","LSSGAGFYS ","LSSGAGFZA ","LSSGAGFZS ","LSSGAGMXA ", & + "LSSGAGMXS ","LSSGAGMYA ","LSSGAGMYS ","LSSGAGMZA ","LSSGAGMZS ","LSSGAGP ","LSSGAGPXA ", & + "LSSGAGPXS ","LSSGAGV ","LSSGAGVXA ","LSSGAGVXS ","LSSHFTFXA ","LSSHFTFXS ","LSSHFTFYA ", & + "LSSHFTFYS ","LSSHFTFZA ","LSSHFTFZS ","LSSHFTMXA ","LSSHFTMXS ","LSSHFTPWR ","LSSHFTTQ ", & + "LSSTIPA ","LSSTIPAXA ","LSSTIPAXS ","LSSTIPMYA ","LSSTIPMYS ","LSSTIPMZA ","LSSTIPMZS ", & + "LSSTIPP ","LSSTIPPXA ","LSSTIPPXS ","LSSTIPV ","LSSTIPVXA ","LSSTIPVXS ","NACYAW ", & + "NACYAWA ","NACYAWP ","NACYAWV ","NCIMURAXS ","NCIMURAYS ","NCIMURAZS ","NCIMURVXS ", & + "NCIMURVYS ","NCIMURVZS ","NCIMUTAGXS","NCIMUTAGYS","NCIMUTAGZS","NCIMUTAXS ","NCIMUTAYS ", & + "NCIMUTAZS ","NCIMUTVXS ","NCIMUTVYS ","NCIMUTVZS ","OMEGAYF ","OOPDEFL1 ","OOPDEFL2 ", & + "OOPDEFL3 ","PTCHDEFL1 ","PTCHDEFL2 ","PTCHDEFL3 ","PTCHPMZB1 ","PTCHPMZB2 ","PTCHPMZB3 ", & + "PTCHPMZC1 ","PTCHPMZC2 ","PTCHPMZC3 ","PTFMHEAVE ","PTFMPITCH ","PTFMRAXI ","PTFMRAXT ", & + "PTFMRAYI ","PTFMRAYT ","PTFMRAZI ","PTFMRAZT ","PTFMRDXI ","PTFMRDYI ","PTFMRDZI ", & + "PTFMROLL ","PTFMRVXI ","PTFMRVXT ","PTFMRVYI ","PTFMRVYT ","PTFMRVZI ","PTFMRVZT ", & + "PTFMSURGE ","PTFMSWAY ","PTFMTAGXI ","PTFMTAGXT ","PTFMTAGYI ","PTFMTAGYT ","PTFMTAGZI ", & + "PTFMTAGZT ","PTFMTAXI ","PTFMTAXT ","PTFMTAYI ","PTFMTAYT ","PTFMTAZI ","PTFMTAZT ", & + "PTFMTDXI ","PTFMTDXT ","PTFMTDYI ","PTFMTDYT ","PTFMTDZI ","PTFMTDZT ","PTFMTVXI ", & + "PTFMTVXT ","PTFMTVYI ","PTFMTVYT ","PTFMTVZI ","PTFMTVZT ","PTFMYAW ","QD2_B1E1 ", & + "QD2_B1F1 ","QD2_B1F2 ","QD2_B2E1 ","QD2_B2F1 ","QD2_B2F2 ","QD2_B3E1 ","QD2_B3F1 ", & + "QD2_B3F2 ","QD2_DRTR ","QD2_GEAZ ","QD2_HV ","QD2_P ","QD2_R ","QD2_RFRL ", & + "QD2_SG ","QD2_SW ","QD2_TEET ","QD2_TFA1 ","QD2_TFA2 ","QD2_TFRL ","QD2_TSS1 ", & + "QD2_TSS2 ","QD2_Y ","QD2_YAW ","QD_B1E1 ","QD_B1F1 ","QD_B1F2 ","QD_B2E1 ", & + "QD_B2F1 ","QD_B2F2 ","QD_B3E1 ","QD_B3F1 ","QD_B3F2 ","QD_DRTR ","QD_GEAZ ", & + "QD_HV ","QD_P ","QD_R ","QD_RFRL ","QD_SG ","QD_SW ","QD_TEET ", & + "QD_TFA1 ","QD_TFA2 ","QD_TFRL ","QD_TSS1 ","QD_TSS2 ","QD_Y ","QD_YAW ", & + "Q_B1E1 ","Q_B1F1 ","Q_B1F2 ","Q_B2E1 ","Q_B2F1 ","Q_B2F2 ","Q_B3E1 ", & + "Q_B3F1 ","Q_B3F2 ","Q_DRTR ","Q_GEAZ ","Q_HV ","Q_P ","Q_R ", & + "Q_RFRL ","Q_SG ","Q_SW ","Q_TEET ","Q_TFA1 ","Q_TFA2 ","Q_TFRL ", & + "Q_TSS1 ","Q_TSS2 ","Q_Y ","Q_YAW ","RFRLBRM ","ROLLDEFL1 ","ROLLDEFL2 ", & + "ROLLDEFL3 ","ROOTFXB1 ","ROOTFXB2 ","ROOTFXB3 ","ROOTFXC1 ","ROOTFXC2 ","ROOTFXC3 ", & + "ROOTFYB1 ","ROOTFYB2 ","ROOTFYB3 ","ROOTFYC1 ","ROOTFYC2 ","ROOTFYC3 ","ROOTFZB1 ", & + "ROOTFZB2 ","ROOTFZB3 ","ROOTFZC1 ","ROOTFZC2 ","ROOTFZC3 ","ROOTMEDG1 ","ROOTMEDG2 ", & + "ROOTMEDG3 ","ROOTMFLP1 ","ROOTMFLP2 ","ROOTMFLP3 ","ROOTMIP1 ","ROOTMIP2 ","ROOTMIP3 ", & + "ROOTMOOP1 ","ROOTMOOP2 ","ROOTMOOP3 ","ROOTMXB1 ","ROOTMXB2 ","ROOTMXB3 ","ROOTMXC1 ", & + "ROOTMXC2 ","ROOTMXC3 ","ROOTMYB1 ","ROOTMYB2 ","ROOTMYB3 ","ROOTMYC1 ","ROOTMYC2 ", & + "ROOTMYC3 ","ROOTMZB1 ","ROOTMZB2 ","ROOTMZB3 ","ROOTMZC1 ","ROOTMZC2 ","ROOTMZC3 ", & + "ROTACCEL ","ROTFURL ","ROTFURLA ","ROTFURLP ","ROTFURLV ","ROTPWR ","ROTSPEED ", & + "ROTTEETA ","ROTTEETP ","ROTTEETV ","ROTTHRUST ","ROTTORQ ","SPN1ALGXB1","SPN1ALGXB2", & + "SPN1ALGXB3","SPN1ALGYB1","SPN1ALGYB2","SPN1ALGYB3","SPN1ALGZB1","SPN1ALGZB2","SPN1ALGZB3", & + "SPN1ALXB1 ","SPN1ALXB2 ","SPN1ALXB3 ","SPN1ALYB1 ","SPN1ALYB2 ","SPN1ALYB3 ","SPN1ALZB1 ", & + "SPN1ALZB2 ","SPN1ALZB3 ","SPN1FLXB1 ","SPN1FLXB2 ","SPN1FLXB3 ","SPN1FLYB1 ","SPN1FLYB2 ", & + "SPN1FLYB3 ","SPN1FLZB1 ","SPN1FLZB2 ","SPN1FLZB3 ","SPN1MLXB1 ","SPN1MLXB2 ","SPN1MLXB3 ", & + "SPN1MLYB1 ","SPN1MLYB2 ","SPN1MLYB3 ","SPN1MLZB1 ","SPN1MLZB2 ","SPN1MLZB3 ","SPN1RDXB1 ", & + "SPN1RDXB2 ","SPN1RDXB3 ","SPN1RDYB1 ","SPN1RDYB2 ","SPN1RDYB3 ","SPN1RDZB1 ","SPN1RDZB2 ", & + "SPN1RDZB3 ","SPN1TDXB1 ","SPN1TDXB2 ","SPN1TDXB3 ","SPN1TDYB1 ","SPN1TDYB2 ","SPN1TDYB3 ", & + "SPN1TDZB1 ","SPN1TDZB2 ","SPN1TDZB3 ","SPN2ALGXB1","SPN2ALGXB2","SPN2ALGXB3","SPN2ALGYB1", & + "SPN2ALGYB2","SPN2ALGYB3","SPN2ALGZB1","SPN2ALGZB2","SPN2ALGZB3","SPN2ALXB1 ","SPN2ALXB2 ", & + "SPN2ALXB3 ","SPN2ALYB1 ","SPN2ALYB2 ","SPN2ALYB3 ","SPN2ALZB1 ","SPN2ALZB2 ","SPN2ALZB3 ", & + "SPN2FLXB1 ","SPN2FLXB2 ","SPN2FLXB3 ","SPN2FLYB1 ","SPN2FLYB2 ","SPN2FLYB3 ","SPN2FLZB1 ", & + "SPN2FLZB2 ","SPN2FLZB3 ","SPN2MLXB1 ","SPN2MLXB2 ","SPN2MLXB3 ","SPN2MLYB1 ","SPN2MLYB2 ", & + "SPN2MLYB3 ","SPN2MLZB1 ","SPN2MLZB2 ","SPN2MLZB3 ","SPN2RDXB1 ","SPN2RDXB2 ","SPN2RDXB3 ", & + "SPN2RDYB1 ","SPN2RDYB2 ","SPN2RDYB3 ","SPN2RDZB1 ","SPN2RDZB2 ","SPN2RDZB3 ","SPN2TDXB1 ", & + "SPN2TDXB2 ","SPN2TDXB3 ","SPN2TDYB1 ","SPN2TDYB2 ","SPN2TDYB3 ","SPN2TDZB1 ","SPN2TDZB2 ", & + "SPN2TDZB3 ","SPN3ALGXB1","SPN3ALGXB2","SPN3ALGXB3","SPN3ALGYB1","SPN3ALGYB2","SPN3ALGYB3", & + "SPN3ALGZB1","SPN3ALGZB2","SPN3ALGZB3","SPN3ALXB1 ","SPN3ALXB2 ","SPN3ALXB3 ","SPN3ALYB1 ", & + "SPN3ALYB2 ","SPN3ALYB3 ","SPN3ALZB1 ","SPN3ALZB2 ","SPN3ALZB3 ","SPN3FLXB1 ","SPN3FLXB2 ", & + "SPN3FLXB3 ","SPN3FLYB1 ","SPN3FLYB2 ","SPN3FLYB3 ","SPN3FLZB1 ","SPN3FLZB2 ","SPN3FLZB3 ", & + "SPN3MLXB1 ","SPN3MLXB2 ","SPN3MLXB3 ","SPN3MLYB1 ","SPN3MLYB2 ","SPN3MLYB3 ","SPN3MLZB1 ", & + "SPN3MLZB2 ","SPN3MLZB3 ","SPN3RDXB1 ","SPN3RDXB2 ","SPN3RDXB3 ","SPN3RDYB1 ","SPN3RDYB2 ", & + "SPN3RDYB3 ","SPN3RDZB1 ","SPN3RDZB2 ","SPN3RDZB3 ","SPN3TDXB1 ","SPN3TDXB2 ","SPN3TDXB3 ", & + "SPN3TDYB1 ","SPN3TDYB2 ","SPN3TDYB3 ","SPN3TDZB1 ","SPN3TDZB2 ","SPN3TDZB3 ","SPN4ALGXB1", & + "SPN4ALGXB2","SPN4ALGXB3","SPN4ALGYB1","SPN4ALGYB2","SPN4ALGYB3","SPN4ALGZB1","SPN4ALGZB2", & + "SPN4ALGZB3","SPN4ALXB1 ","SPN4ALXB2 ","SPN4ALXB3 ","SPN4ALYB1 ","SPN4ALYB2 ","SPN4ALYB3 ", & + "SPN4ALZB1 ","SPN4ALZB2 ","SPN4ALZB3 ","SPN4FLXB1 ","SPN4FLXB2 ","SPN4FLXB3 ","SPN4FLYB1 ", & + "SPN4FLYB2 ","SPN4FLYB3 ","SPN4FLZB1 ","SPN4FLZB2 ","SPN4FLZB3 ","SPN4MLXB1 ","SPN4MLXB2 ", & + "SPN4MLXB3 ","SPN4MLYB1 ","SPN4MLYB2 ","SPN4MLYB3 ","SPN4MLZB1 ","SPN4MLZB2 ","SPN4MLZB3 ", & + "SPN4RDXB1 ","SPN4RDXB2 ","SPN4RDXB3 ","SPN4RDYB1 ","SPN4RDYB2 ","SPN4RDYB3 ","SPN4RDZB1 ", & + "SPN4RDZB2 ","SPN4RDZB3 ","SPN4TDXB1 ","SPN4TDXB2 ","SPN4TDXB3 ","SPN4TDYB1 ","SPN4TDYB2 ", & + "SPN4TDYB3 ","SPN4TDZB1 ","SPN4TDZB2 ","SPN4TDZB3 ","SPN5ALGXB1","SPN5ALGXB2","SPN5ALGXB3", & + "SPN5ALGYB1","SPN5ALGYB2","SPN5ALGYB3","SPN5ALGZB1","SPN5ALGZB2","SPN5ALGZB3","SPN5ALXB1 ", & + "SPN5ALXB2 ","SPN5ALXB3 ","SPN5ALYB1 ","SPN5ALYB2 ","SPN5ALYB3 ","SPN5ALZB1 ","SPN5ALZB2 ", & + "SPN5ALZB3 ","SPN5FLXB1 ","SPN5FLXB2 ","SPN5FLXB3 ","SPN5FLYB1 ","SPN5FLYB2 ","SPN5FLYB3 ", & + "SPN5FLZB1 ","SPN5FLZB2 ","SPN5FLZB3 ","SPN5MLXB1 ","SPN5MLXB2 ","SPN5MLXB3 ","SPN5MLYB1 ", & + "SPN5MLYB2 ","SPN5MLYB3 ","SPN5MLZB1 ","SPN5MLZB2 ","SPN5MLZB3 ","SPN5RDXB1 ","SPN5RDXB2 ", & + "SPN5RDXB3 ","SPN5RDYB1 ","SPN5RDYB2 ","SPN5RDYB3 ","SPN5RDZB1 ","SPN5RDZB2 ","SPN5RDZB3 ", & + "SPN5TDXB1 ","SPN5TDXB2 ","SPN5TDXB3 ","SPN5TDYB1 ","SPN5TDYB2 ","SPN5TDYB3 ","SPN5TDZB1 ", & + "SPN5TDZB2 ","SPN5TDZB3 ","SPN6ALGXB1","SPN6ALGXB2","SPN6ALGXB3","SPN6ALGYB1","SPN6ALGYB2", & + "SPN6ALGYB3","SPN6ALGZB1","SPN6ALGZB2","SPN6ALGZB3","SPN6ALXB1 ","SPN6ALXB2 ","SPN6ALXB3 ", & + "SPN6ALYB1 ","SPN6ALYB2 ","SPN6ALYB3 ","SPN6ALZB1 ","SPN6ALZB2 ","SPN6ALZB3 ","SPN6FLXB1 ", & + "SPN6FLXB2 ","SPN6FLXB3 ","SPN6FLYB1 ","SPN6FLYB2 ","SPN6FLYB3 ","SPN6FLZB1 ","SPN6FLZB2 ", & + "SPN6FLZB3 ","SPN6MLXB1 ","SPN6MLXB2 ","SPN6MLXB3 ","SPN6MLYB1 ","SPN6MLYB2 ","SPN6MLYB3 ", & + "SPN6MLZB1 ","SPN6MLZB2 ","SPN6MLZB3 ","SPN6RDXB1 ","SPN6RDXB2 ","SPN6RDXB3 ","SPN6RDYB1 ", & + "SPN6RDYB2 ","SPN6RDYB3 ","SPN6RDZB1 ","SPN6RDZB2 ","SPN6RDZB3 ","SPN6TDXB1 ","SPN6TDXB2 ", & + "SPN6TDXB3 ","SPN6TDYB1 ","SPN6TDYB2 ","SPN6TDYB3 ","SPN6TDZB1 ","SPN6TDZB2 ","SPN6TDZB3 ", & + "SPN7ALGXB1","SPN7ALGXB2","SPN7ALGXB3","SPN7ALGYB1","SPN7ALGYB2","SPN7ALGYB3","SPN7ALGZB1", & + "SPN7ALGZB2","SPN7ALGZB3","SPN7ALXB1 ","SPN7ALXB2 ","SPN7ALXB3 ","SPN7ALYB1 ","SPN7ALYB2 ", & + "SPN7ALYB3 ","SPN7ALZB1 ","SPN7ALZB2 ","SPN7ALZB3 ","SPN7FLXB1 ","SPN7FLXB2 ","SPN7FLXB3 ", & + "SPN7FLYB1 ","SPN7FLYB2 ","SPN7FLYB3 ","SPN7FLZB1 ","SPN7FLZB2 ","SPN7FLZB3 ","SPN7MLXB1 ", & + "SPN7MLXB2 ","SPN7MLXB3 ","SPN7MLYB1 ","SPN7MLYB2 ","SPN7MLYB3 ","SPN7MLZB1 ","SPN7MLZB2 ", & + "SPN7MLZB3 ","SPN7RDXB1 ","SPN7RDXB2 ","SPN7RDXB3 ","SPN7RDYB1 ","SPN7RDYB2 ","SPN7RDYB3 ", & + "SPN7RDZB1 ","SPN7RDZB2 ","SPN7RDZB3 ","SPN7TDXB1 ","SPN7TDXB2 ","SPN7TDXB3 ","SPN7TDYB1 ", & + "SPN7TDYB2 ","SPN7TDYB3 ","SPN7TDZB1 ","SPN7TDZB2 ","SPN7TDZB3 ","SPN8ALGXB1","SPN8ALGXB2", & + "SPN8ALGXB3","SPN8ALGYB1","SPN8ALGYB2","SPN8ALGYB3","SPN8ALGZB1","SPN8ALGZB2","SPN8ALGZB3", & + "SPN8ALXB1 ","SPN8ALXB2 ","SPN8ALXB3 ","SPN8ALYB1 ","SPN8ALYB2 ","SPN8ALYB3 ","SPN8ALZB1 ", & + "SPN8ALZB2 ","SPN8ALZB3 ","SPN8FLXB1 ","SPN8FLXB2 ","SPN8FLXB3 ","SPN8FLYB1 ","SPN8FLYB2 ", & + "SPN8FLYB3 ","SPN8FLZB1 ","SPN8FLZB2 ","SPN8FLZB3 ","SPN8MLXB1 ","SPN8MLXB2 ","SPN8MLXB3 ", & + "SPN8MLYB1 ","SPN8MLYB2 ","SPN8MLYB3 ","SPN8MLZB1 ","SPN8MLZB2 ","SPN8MLZB3 ","SPN8RDXB1 ", & + "SPN8RDXB2 ","SPN8RDXB3 ","SPN8RDYB1 ","SPN8RDYB2 ","SPN8RDYB3 ","SPN8RDZB1 ","SPN8RDZB2 ", & + "SPN8RDZB3 ","SPN8TDXB1 ","SPN8TDXB2 ","SPN8TDXB3 ","SPN8TDYB1 ","SPN8TDYB2 ","SPN8TDYB3 ", & + "SPN8TDZB1 ","SPN8TDZB2 ","SPN8TDZB3 ","SPN9ALGXB1","SPN9ALGXB2","SPN9ALGXB3","SPN9ALGYB1", & + "SPN9ALGYB2","SPN9ALGYB3","SPN9ALGZB1","SPN9ALGZB2","SPN9ALGZB3","SPN9ALXB1 ","SPN9ALXB2 ", & + "SPN9ALXB3 ","SPN9ALYB1 ","SPN9ALYB2 ","SPN9ALYB3 ","SPN9ALZB1 ","SPN9ALZB2 ","SPN9ALZB3 ", & + "SPN9FLXB1 ","SPN9FLXB2 ","SPN9FLXB3 ","SPN9FLYB1 ","SPN9FLYB2 ","SPN9FLYB3 ","SPN9FLZB1 ", & + "SPN9FLZB2 ","SPN9FLZB3 ","SPN9MLXB1 ","SPN9MLXB2 ","SPN9MLXB3 ","SPN9MLYB1 ","SPN9MLYB2 ", & + "SPN9MLYB3 ","SPN9MLZB1 ","SPN9MLZB2 ","SPN9MLZB3 ","SPN9RDXB1 ","SPN9RDXB2 ","SPN9RDXB3 ", & + "SPN9RDYB1 ","SPN9RDYB2 ","SPN9RDYB3 ","SPN9RDZB1 ","SPN9RDZB2 ","SPN9RDZB3 ","SPN9TDXB1 ", & + "SPN9TDXB2 ","SPN9TDXB3 ","SPN9TDYB1 ","SPN9TDYB2 ","SPN9TDYB3 ","SPN9TDZB1 ","SPN9TDZB2 ", & + "SPN9TDZB3 ","TAILFURL ","TAILFURLA ","TAILFURLP ","TAILFURLV ","TEETAYA ","TEETDEFL ", & + "TEETPYA ","TEETVYA ","TFRLBRM ","TIP2TWR1 ","TIP2TWR2 ","TIP2TWR3 ","TIPALGXB1 ", & + "TIPALGXB2 ","TIPALGXB3 ","TIPALGYB1 ","TIPALGYB2 ","TIPALGYB3 ","TIPALGZB1 ","TIPALGZB2 ", & + "TIPALGZB3 ","TIPALXB1 ","TIPALXB2 ","TIPALXB3 ","TIPALYB1 ","TIPALYB2 ","TIPALYB3 ", & + "TIPALZB1 ","TIPALZB2 ","TIPALZB3 ","TIPCLRNC1 ","TIPCLRNC2 ","TIPCLRNC3 ","TIPDXB1 ", & + "TIPDXB2 ","TIPDXB3 ","TIPDXC1 ","TIPDXC2 ","TIPDXC3 ","TIPDYB1 ","TIPDYB2 ", & + "TIPDYB3 ","TIPDYC1 ","TIPDYC2 ","TIPDYC3 ","TIPDZB1 ","TIPDZB2 ","TIPDZB3 ", & + "TIPDZC1 ","TIPDZC2 ","TIPDZC3 ","TIPRDXB1 ","TIPRDXB2 ","TIPRDXB3 ","TIPRDYB1 ", & + "TIPRDYB2 ","TIPRDYB3 ","TIPRDZB1 ","TIPRDZB2 ","TIPRDZB3 ","TIPRDZC1 ","TIPRDZC2 ", & + "TIPRDZC3 ","TTDSPAX ","TTDSPFA ","TTDSPPTCH ","TTDSPROLL ","TTDSPSS ","TTDSPTWST ", & + "TWHT1ALGXT","TWHT1ALGYT","TWHT1ALGZT","TWHT1ALXT ","TWHT1ALYT ","TWHT1ALZT ","TWHT1FLXT ", & + "TWHT1FLYT ","TWHT1FLZT ","TWHT1MLXT ","TWHT1MLYT ","TWHT1MLZT ","TWHT1RDXT ","TWHT1RDYT ", & + "TWHT1RDZT ","TWHT1RPXI ","TWHT1RPYI ","TWHT1RPZI ","TWHT1TDXT ","TWHT1TDYT ","TWHT1TDZT ", & + "TWHT1TPXI ","TWHT1TPYI ","TWHT1TPZI ","TWHT2ALGXT","TWHT2ALGYT","TWHT2ALGZT","TWHT2ALXT ", & + "TWHT2ALYT ","TWHT2ALZT ","TWHT2FLXT ","TWHT2FLYT ","TWHT2FLZT ","TWHT2MLXT ","TWHT2MLYT ", & + "TWHT2MLZT ","TWHT2RDXT ","TWHT2RDYT ","TWHT2RDZT ","TWHT2RPXI ","TWHT2RPYI ","TWHT2RPZI ", & + "TWHT2TDXT ","TWHT2TDYT ","TWHT2TDZT ","TWHT2TPXI ","TWHT2TPYI ","TWHT2TPZI ","TWHT3ALGXT", & + "TWHT3ALGYT","TWHT3ALGZT","TWHT3ALXT ","TWHT3ALYT ","TWHT3ALZT ","TWHT3FLXT ","TWHT3FLYT ", & + "TWHT3FLZT ","TWHT3MLXT ","TWHT3MLYT ","TWHT3MLZT ","TWHT3RDXT ","TWHT3RDYT ","TWHT3RDZT ", & + "TWHT3RPXI ","TWHT3RPYI ","TWHT3RPZI ","TWHT3TDXT ","TWHT3TDYT ","TWHT3TDZT ","TWHT3TPXI ", & + "TWHT3TPYI ","TWHT3TPZI ","TWHT4ALGXT","TWHT4ALGYT","TWHT4ALGZT","TWHT4ALXT ","TWHT4ALYT ", & + "TWHT4ALZT ","TWHT4FLXT ","TWHT4FLYT ","TWHT4FLZT ","TWHT4MLXT ","TWHT4MLYT ","TWHT4MLZT ", & + "TWHT4RDXT ","TWHT4RDYT ","TWHT4RDZT ","TWHT4RPXI ","TWHT4RPYI ","TWHT4RPZI ","TWHT4TDXT ", & + "TWHT4TDYT ","TWHT4TDZT ","TWHT4TPXI ","TWHT4TPYI ","TWHT4TPZI ","TWHT5ALGXT","TWHT5ALGYT", & + "TWHT5ALGZT","TWHT5ALXT ","TWHT5ALYT ","TWHT5ALZT ","TWHT5FLXT ","TWHT5FLYT ","TWHT5FLZT ", & + "TWHT5MLXT ","TWHT5MLYT ","TWHT5MLZT ","TWHT5RDXT ","TWHT5RDYT ","TWHT5RDZT ","TWHT5RPXI ", & + "TWHT5RPYI ","TWHT5RPZI ","TWHT5TDXT ","TWHT5TDYT ","TWHT5TDZT ","TWHT5TPXI ","TWHT5TPYI ", & + "TWHT5TPZI ","TWHT6ALGXT","TWHT6ALGYT","TWHT6ALGZT","TWHT6ALXT ","TWHT6ALYT ","TWHT6ALZT ", & + "TWHT6FLXT ","TWHT6FLYT ","TWHT6FLZT ","TWHT6MLXT ","TWHT6MLYT ","TWHT6MLZT ","TWHT6RDXT ", & + "TWHT6RDYT ","TWHT6RDZT ","TWHT6RPXI ","TWHT6RPYI ","TWHT6RPZI ","TWHT6TDXT ","TWHT6TDYT ", & + "TWHT6TDZT ","TWHT6TPXI ","TWHT6TPYI ","TWHT6TPZI ","TWHT7ALGXT","TWHT7ALGYT","TWHT7ALGZT", & + "TWHT7ALXT ","TWHT7ALYT ","TWHT7ALZT ","TWHT7FLXT ","TWHT7FLYT ","TWHT7FLZT ","TWHT7MLXT ", & + "TWHT7MLYT ","TWHT7MLZT ","TWHT7RDXT ","TWHT7RDYT ","TWHT7RDZT ","TWHT7RPXI ","TWHT7RPYI ", & + "TWHT7RPZI ","TWHT7TDXT ","TWHT7TDYT ","TWHT7TDZT ","TWHT7TPXI ","TWHT7TPYI ","TWHT7TPZI ", & + "TWHT8ALGXT","TWHT8ALGYT","TWHT8ALGZT","TWHT8ALXT ","TWHT8ALYT ","TWHT8ALZT ","TWHT8FLXT ", & + "TWHT8FLYT ","TWHT8FLZT ","TWHT8MLXT ","TWHT8MLYT ","TWHT8MLZT ","TWHT8RDXT ","TWHT8RDYT ", & + "TWHT8RDZT ","TWHT8RPXI ","TWHT8RPYI ","TWHT8RPZI ","TWHT8TDXT ","TWHT8TDYT ","TWHT8TDZT ", & + "TWHT8TPXI ","TWHT8TPYI ","TWHT8TPZI ","TWHT9ALGXT","TWHT9ALGYT","TWHT9ALGZT","TWHT9ALXT ", & + "TWHT9ALYT ","TWHT9ALZT ","TWHT9FLXT ","TWHT9FLYT ","TWHT9FLZT ","TWHT9MLXT ","TWHT9MLYT ", & + "TWHT9MLZT ","TWHT9RDXT ","TWHT9RDYT ","TWHT9RDZT ","TWHT9RPXI ","TWHT9RPYI ","TWHT9RPZI ", & + "TWHT9TDXT ","TWHT9TDYT ","TWHT9TDZT ","TWHT9TPXI ","TWHT9TPYI ","TWHT9TPZI ","TWRBSFXT ", & + "TWRBSFYT ","TWRBSFZT ","TWRBSMXT ","TWRBSMYT ","TWRBSMZT ","TWRCLRNC1 ","TWRCLRNC2 ", & + "TWRCLRNC3 ","TWRTPTDXI ","TWRTPTDYI ","TWRTPTDZI ","TWSTDEFL1 ","TWSTDEFL2 ","TWSTDEFL3 ", & + "YAWACCEL ","YAWAZN ","YAWAZP ","YAWBRFXN ","YAWBRFXP ","YAWBRFYN ","YAWBRFYP ", & + "YAWBRFZN ","YAWBRFZP ","YAWBRMXN ","YAWBRMXP ","YAWBRMYN ","YAWBRMYP ","YAWBRMZN ", & + "YAWBRMZP ","YAWBRRAXP ","YAWBRRAYP ","YAWBRRAZP ","YAWBRRDXT ","YAWBRRDYT ","YAWBRRDZT ", & + "YAWBRRVXP ","YAWBRRVYP ","YAWBRRVZP ","YAWBRTAGXP","YAWBRTAGYP","YAWBRTAGZP","YAWBRTAXP ", & + "YAWBRTAYP ","YAWBRTAZP ","YAWBRTDXI ","YAWBRTDXP ","YAWBRTDXT ","YAWBRTDYI ","YAWBRTDYP ", & + "YAWBRTDYT ","YAWBRTDZI ","YAWBRTDZP ","YAWBRTDZT ","YAWBRTVXP ","YAWBRTVYP ","YAWBRTVZP ", & + "YAWFRIMFP ","YAWFRIMOM ","YAWFRIMZ ","YAWPOS ","YAWPZN ","YAWPZP ","YAWRATE ", & + "YAWVZN ","YAWVZP "/) + INTEGER(IntKi), PARAMETER :: ParamIndxAry(1115) = (/ & ! This lists the index into AllOuts(:) of the allowed parameters ValidParamAry(:) LSSTipPxa , PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , & - HSShftA , HSShftV , HSSBrTq , HSShftA , HSShftPwr , HSShftTq , HSShftV , & - TipDyc1 , TipDyc2 , TipDyc3 , LSSGagAxa , LSSGagAxa , LSSGagAxa , LSShftFxa , & - LSShftFxa , LSShftFya , LSShftFys , LSShftFza , LSShftFzs , LSShftMxa , LSShftMxa , & - LSSGagMya , LSSGagMys , LSSGagMza , LSSGagMzs , LSSGagPxa , LSSGagPxa , LSSGagPxa , & - LSSGagVxa , LSSGagVxa , LSSGagVxa , LSShftFxa , LSShftFxa , LSShftFya , LSShftFys , & - LSShftFza , LSShftFzs , LSShftMxa , LSShftMxa , RotPwr , LSShftMxa , LSSTipAxa , & - LSSTipAxa , LSSTipAxa , LSSTipMya , LSSTipMys , LSSTipMza , LSSTipMzs , LSSTipPxa , & - LSSTipPxa , LSSTipPxa , LSSTipVxa , LSSTipVxa , LSSTipVxa , YawPzn , YawAzn , & - YawPzn , YawVzn , NcIMURAxs , NcIMURAys , NcIMURAzs , NcIMURVxs , NcIMURVys , & - NcIMURVzs , NcIMUTAgxs , NcIMUTAgys , NcIMUTAgzs , NcIMUTAxs , NcIMUTAys , NcIMUTAzs , & - NcIMUTVxs , NcIMUTVys , NcIMUTVzs , TipDxc1 , TipDxc2 , TipDxc3 , TipRDyb1 , & - TipRDyb2 , TipRDyb3 , PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , PtchPMzc1 , PtchPMzc2 , & - PtchPMzc3 , PtfmTDzi , PtfmRDyi , PtfmRAxi , PtfmRAxt , PtfmRAyi , PtfmRAyt , & - PtfmRAzi , PtfmRAzt , PtfmRDxi , PtfmRDyi , PtfmRDzi , PtfmRDxi , PtfmRVxi , & - PtfmRVxt , PtfmRVyi , PtfmRVyt , PtfmRVzi , PtfmRVzt , PtfmTDxi , PtfmTDyi , & - PtfmTAgxi , PtfmTAgxt , PtfmTAgyi , PtfmTAgyt , PtfmTAgzi , PtfmTAgzt , PtfmTAxi , & - PtfmTAxt , PtfmTAyi , PtfmTAyt , PtfmTAzi , PtfmTAzt , PtfmTDxi , PtfmTDxt , & - PtfmTDyi , PtfmTDyt , PtfmTDzi , PtfmTDzt , PtfmTVxi , PtfmTVxt , PtfmTVyi , & - PtfmTVyt , PtfmTVzi , PtfmTVzt , PtfmRDzi , QD2_B1E1 , QD2_B1F1 , QD2_B1F2 , & - QD2_B2E1 , QD2_B2F1 , QD2_B2F2 , QD2_B3E1 , QD2_B3F1 , QD2_B3F2 , QD2_DrTr , & - QD2_GeAz , QD2_Hv , QD2_P , QD2_R , QD2_RFrl , QD2_Sg , QD2_Sw , & - QD2_Teet , QD2_TFA1 , QD2_TFA2 , QD2_TFrl , QD2_TSS1 , QD2_TSS2 , QD2_Y , & - QD2_Yaw , QD_B1E1 , QD_B1F1 , QD_B1F2 , QD_B2E1 , QD_B2F1 , QD_B2F2 , & - QD_B3E1 , QD_B3F1 , QD_B3F2 , QD_DrTr , QD_GeAz , QD_Hv , QD_P , & - QD_R , QD_RFrl , QD_Sg , QD_Sw , QD_Teet , QD_TFA1 , QD_TFA2 , & - QD_TFrl , QD_TSS1 , QD_TSS2 , QD_Y , QD_Yaw , Q_B1E1 , Q_B1F1 , & - Q_B1F2 , Q_B2E1 , Q_B2F1 , Q_B2F2 , Q_B3E1 , Q_B3F1 , Q_B3F2 , & - Q_DrTr , Q_GeAz , Q_Hv , Q_P , Q_R , Q_RFrl , Q_Sg , & - Q_Sw , Q_Teet , Q_TFA1 , Q_TFA2 , Q_TFrl , Q_TSS1 , Q_TSS2 , & - Q_Y , Q_Yaw , RFrlBrM , TipRDxb1 , TipRDxb2 , TipRDxb3 , RootFxb1 , & - RootFxb2 , RootFxb3 , RootFxc1 , RootFxc2 , RootFxc3 , RootFyb1 , RootFyb2 , & - RootFyb3 , RootFyc1 , RootFyc2 , RootFyc3 , RootFzc1 , RootFzc2 , RootFzc3 , & - RootFzc1 , RootFzc2 , RootFzc3 , RootMxb1 , RootMxb2 , RootMxb3 , RootMyb1 , & - RootMyb2 , RootMyb3 , RootMxc1 , RootMxc2 , RootMxc3 , RootMyc1 , RootMyc2 , & - RootMyc3 , RootMxb1 , RootMxb2 , RootMxb3 , RootMxc1 , RootMxc2 , RootMxc3 , & - RootMyb1 , RootMyb2 , RootMyb3 , RootMyc1 , RootMyc2 , RootMyc3 , RootMzc1 , & - RootMzc2 , RootMzc3 , RootMzc1 , RootMzc2 , RootMzc3 , LSSTipAxa , RotFurlP , & - RotFurlA , RotFurlP , RotFurlV , RotPwr , LSSTipVxa , TeetAya , TeetPya , & - TeetVya , LSShftFxa , LSShftMxa , Spn1ALgxb1 , Spn1ALgxb2 , Spn1ALgxb3 , Spn1ALgyb1 , & - Spn1ALgyb2 , Spn1ALgyb3 , Spn1ALgzb1 , Spn1ALgzb2 , Spn1ALgzb3 , Spn1ALxb1 , Spn1ALxb2 , & - Spn1ALxb3 , Spn1ALyb1 , Spn1ALyb2 , Spn1ALyb3 , Spn1ALzb1 , Spn1ALzb2 , Spn1ALzb3 , & - Spn1FLxb1 , Spn1FLxb2 , Spn1FLxb3 , Spn1FLyb1 , Spn1FLyb2 , Spn1FLyb3 , Spn1FLzb1 , & - Spn1FLzb2 , Spn1FLzb3 , Spn1MLxb1 , Spn1MLxb2 , Spn1MLxb3 , Spn1MLyb1 , Spn1MLyb2 , & - Spn1MLyb3 , Spn1MLzb1 , Spn1MLzb2 , Spn1MLzb3 , Spn1RDxb1 , Spn1RDxb2 , Spn1RDxb3 , & - Spn1RDyb1 , Spn1RDyb2 , Spn1RDyb3 , Spn1RDzb1 , Spn1RDzb2 , Spn1RDzb3 , Spn1TDxb1 , & - Spn1TDxb2 , Spn1TDxb3 , Spn1TDyb1 , Spn1TDyb2 , Spn1TDyb3 , Spn1TDzb1 , Spn1TDzb2 , & - Spn1TDzb3 , Spn2ALgxb1 , Spn2ALgxb2 , Spn2ALgxb3 , Spn2ALgyb1 , Spn2ALgyb2 , Spn2ALgyb3 , & - Spn2ALgzb1 , Spn2ALgzb2 , Spn2ALgzb3 , Spn2ALxb1 , Spn2ALxb2 , Spn2ALxb3 , Spn2ALyb1 , & - Spn2ALyb2 , Spn2ALyb3 , Spn2ALzb1 , Spn2ALzb2 , Spn2ALzb3 , Spn2FLxb1 , Spn2FLxb2 , & - Spn2FLxb3 , Spn2FLyb1 , Spn2FLyb2 , Spn2FLyb3 , Spn2FLzb1 , Spn2FLzb2 , Spn2FLzb3 , & - Spn2MLxb1 , Spn2MLxb2 , Spn2MLxb3 , Spn2MLyb1 , Spn2MLyb2 , Spn2MLyb3 , Spn2MLzb1 , & - Spn2MLzb2 , Spn2MLzb3 , Spn2RDxb1 , Spn2RDxb2 , Spn2RDxb3 , Spn2RDyb1 , Spn2RDyb2 , & - Spn2RDyb3 , Spn2RDzb1 , Spn2RDzb2 , Spn2RDzb3 , Spn2TDxb1 , Spn2TDxb2 , Spn2TDxb3 , & - Spn2TDyb1 , Spn2TDyb2 , Spn2TDyb3 , Spn2TDzb1 , Spn2TDzb2 , Spn2TDzb3 , Spn3ALgxb1 , & - Spn3ALgxb2 , Spn3ALgxb3 , Spn3ALgyb1 , Spn3ALgyb2 , Spn3ALgyb3 , Spn3ALgzb1 , Spn3ALgzb2 , & - Spn3ALgzb3 , Spn3ALxb1 , Spn3ALxb2 , Spn3ALxb3 , Spn3ALyb1 , Spn3ALyb2 , Spn3ALyb3 , & - Spn3ALzb1 , Spn3ALzb2 , Spn3ALzb3 , Spn3FLxb1 , Spn3FLxb2 , Spn3FLxb3 , Spn3FLyb1 , & - Spn3FLyb2 , Spn3FLyb3 , Spn3FLzb1 , Spn3FLzb2 , Spn3FLzb3 , Spn3MLxb1 , Spn3MLxb2 , & - Spn3MLxb3 , Spn3MLyb1 , Spn3MLyb2 , Spn3MLyb3 , Spn3MLzb1 , Spn3MLzb2 , Spn3MLzb3 , & - Spn3RDxb1 , Spn3RDxb2 , Spn3RDxb3 , Spn3RDyb1 , Spn3RDyb2 , Spn3RDyb3 , Spn3RDzb1 , & - Spn3RDzb2 , Spn3RDzb3 , Spn3TDxb1 , Spn3TDxb2 , Spn3TDxb3 , Spn3TDyb1 , Spn3TDyb2 , & - Spn3TDyb3 , Spn3TDzb1 , Spn3TDzb2 , Spn3TDzb3 , Spn4ALgxb1 , Spn4ALgxb2 , Spn4ALgxb3 , & - Spn4ALgyb1 , Spn4ALgyb2 , Spn4ALgyb3 , Spn4ALgzb1 , Spn4ALgzb2 , Spn4ALgzb3 , Spn4ALxb1 , & - Spn4ALxb2 , Spn4ALxb3 , Spn4ALyb1 , Spn4ALyb2 , Spn4ALyb3 , Spn4ALzb1 , Spn4ALzb2 , & - Spn4ALzb3 , Spn4FLxb1 , Spn4FLxb2 , Spn4FLxb3 , Spn4FLyb1 , Spn4FLyb2 , Spn4FLyb3 , & - Spn4FLzb1 , Spn4FLzb2 , Spn4FLzb3 , Spn4MLxb1 , Spn4MLxb2 , Spn4MLxb3 , Spn4MLyb1 , & - Spn4MLyb2 , Spn4MLyb3 , Spn4MLzb1 , Spn4MLzb2 , Spn4MLzb3 , Spn4RDxb1 , Spn4RDxb2 , & - Spn4RDxb3 , Spn4RDyb1 , Spn4RDyb2 , Spn4RDyb3 , Spn4RDzb1 , Spn4RDzb2 , Spn4RDzb3 , & - Spn4TDxb1 , Spn4TDxb2 , Spn4TDxb3 , Spn4TDyb1 , Spn4TDyb2 , Spn4TDyb3 , Spn4TDzb1 , & - Spn4TDzb2 , Spn4TDzb3 , Spn5ALgxb1 , Spn5ALgxb2 , Spn5ALgxb3 , Spn5ALgyb1 , Spn5ALgyb2 , & - Spn5ALgyb3 , Spn5ALgzb1 , Spn5ALgzb2 , Spn5ALgzb3 , Spn5ALxb1 , Spn5ALxb2 , Spn5ALxb3 , & - Spn5ALyb1 , Spn5ALyb2 , Spn5ALyb3 , Spn5ALzb1 , Spn5ALzb2 , Spn5ALzb3 , Spn5FLxb1 , & - Spn5FLxb2 , Spn5FLxb3 , Spn5FLyb1 , Spn5FLyb2 , Spn5FLyb3 , Spn5FLzb1 , Spn5FLzb2 , & - Spn5FLzb3 , Spn5MLxb1 , Spn5MLxb2 , Spn5MLxb3 , Spn5MLyb1 , Spn5MLyb2 , Spn5MLyb3 , & - Spn5MLzb1 , Spn5MLzb2 , Spn5MLzb3 , Spn5RDxb1 , Spn5RDxb2 , Spn5RDxb3 , Spn5RDyb1 , & - Spn5RDyb2 , Spn5RDyb3 , Spn5RDzb1 , Spn5RDzb2 , Spn5RDzb3 , Spn5TDxb1 , Spn5TDxb2 , & - Spn5TDxb3 , Spn5TDyb1 , Spn5TDyb2 , Spn5TDyb3 , Spn5TDzb1 , Spn5TDzb2 , Spn5TDzb3 , & - Spn6ALgxb1 , Spn6ALgxb2 , Spn6ALgxb3 , Spn6ALgyb1 , Spn6ALgyb2 , Spn6ALgyb3 , Spn6ALgzb1 , & - Spn6ALgzb2 , Spn6ALgzb3 , Spn6ALxb1 , Spn6ALxb2 , Spn6ALxb3 , Spn6ALyb1 , Spn6ALyb2 , & - Spn6ALyb3 , Spn6ALzb1 , Spn6ALzb2 , Spn6ALzb3 , Spn6FLxb1 , Spn6FLxb2 , Spn6FLxb3 , & - Spn6FLyb1 , Spn6FLyb2 , Spn6FLyb3 , Spn6FLzb1 , Spn6FLzb2 , Spn6FLzb3 , Spn6MLxb1 , & - Spn6MLxb2 , Spn6MLxb3 , Spn6MLyb1 , Spn6MLyb2 , Spn6MLyb3 , Spn6MLzb1 , Spn6MLzb2 , & - Spn6MLzb3 , Spn6RDxb1 , Spn6RDxb2 , Spn6RDxb3 , Spn6RDyb1 , Spn6RDyb2 , Spn6RDyb3 , & - Spn6RDzb1 , Spn6RDzb2 , Spn6RDzb3 , Spn6TDxb1 , Spn6TDxb2 , Spn6TDxb3 , Spn6TDyb1 , & - Spn6TDyb2 , Spn6TDyb3 , Spn6TDzb1 , Spn6TDzb2 , Spn6TDzb3 , Spn7ALgxb1 , Spn7ALgxb2 , & - Spn7ALgxb3 , Spn7ALgyb1 , Spn7ALgyb2 , Spn7ALgyb3 , Spn7ALgzb1 , Spn7ALgzb2 , Spn7ALgzb3 , & - Spn7ALxb1 , Spn7ALxb2 , Spn7ALxb3 , Spn7ALyb1 , Spn7ALyb2 , Spn7ALyb3 , Spn7ALzb1 , & - Spn7ALzb2 , Spn7ALzb3 , Spn7FLxb1 , Spn7FLxb2 , Spn7FLxb3 , Spn7FLyb1 , Spn7FLyb2 , & - Spn7FLyb3 , Spn7FLzb1 , Spn7FLzb2 , Spn7FLzb3 , Spn7MLxb1 , Spn7MLxb2 , Spn7MLxb3 , & - Spn7MLyb1 , Spn7MLyb2 , Spn7MLyb3 , Spn7MLzb1 , Spn7MLzb2 , Spn7MLzb3 , Spn7RDxb1 , & - Spn7RDxb2 , Spn7RDxb3 , Spn7RDyb1 , Spn7RDyb2 , Spn7RDyb3 , Spn7RDzb1 , Spn7RDzb2 , & - Spn7RDzb3 , Spn7TDxb1 , Spn7TDxb2 , Spn7TDxb3 , Spn7TDyb1 , Spn7TDyb2 , Spn7TDyb3 , & - Spn7TDzb1 , Spn7TDzb2 , Spn7TDzb3 , Spn8ALgxb1 , Spn8ALgxb2 , Spn8ALgxb3 , Spn8ALgyb1 , & - Spn8ALgyb2 , Spn8ALgyb3 , Spn8ALgzb1 , Spn8ALgzb2 , Spn8ALgzb3 , Spn8ALxb1 , Spn8ALxb2 , & - Spn8ALxb3 , Spn8ALyb1 , Spn8ALyb2 , Spn8ALyb3 , Spn8ALzb1 , Spn8ALzb2 , Spn8ALzb3 , & - Spn8FLxb1 , Spn8FLxb2 , Spn8FLxb3 , Spn8FLyb1 , Spn8FLyb2 , Spn8FLyb3 , Spn8FLzb1 , & - Spn8FLzb2 , Spn8FLzb3 , Spn8MLxb1 , Spn8MLxb2 , Spn8MLxb3 , Spn8MLyb1 , Spn8MLyb2 , & - Spn8MLyb3 , Spn8MLzb1 , Spn8MLzb2 , Spn8MLzb3 , Spn8RDxb1 , Spn8RDxb2 , Spn8RDxb3 , & - Spn8RDyb1 , Spn8RDyb2 , Spn8RDyb3 , Spn8RDzb1 , Spn8RDzb2 , Spn8RDzb3 , Spn8TDxb1 , & - Spn8TDxb2 , Spn8TDxb3 , Spn8TDyb1 , Spn8TDyb2 , Spn8TDyb3 , Spn8TDzb1 , Spn8TDzb2 , & - Spn8TDzb3 , Spn9ALgxb1 , Spn9ALgxb2 , Spn9ALgxb3 , Spn9ALgyb1 , Spn9ALgyb2 , Spn9ALgyb3 , & - Spn9ALgzb1 , Spn9ALgzb2 , Spn9ALgzb3 , Spn9ALxb1 , Spn9ALxb2 , Spn9ALxb3 , Spn9ALyb1 , & - Spn9ALyb2 , Spn9ALyb3 , Spn9ALzb1 , Spn9ALzb2 , Spn9ALzb3 , Spn9FLxb1 , Spn9FLxb2 , & - Spn9FLxb3 , Spn9FLyb1 , Spn9FLyb2 , Spn9FLyb3 , Spn9FLzb1 , Spn9FLzb2 , Spn9FLzb3 , & - Spn9MLxb1 , Spn9MLxb2 , Spn9MLxb3 , Spn9MLyb1 , Spn9MLyb2 , Spn9MLyb3 , Spn9MLzb1 , & - Spn9MLzb2 , Spn9MLzb3 , Spn9RDxb1 , Spn9RDxb2 , Spn9RDxb3 , Spn9RDyb1 , Spn9RDyb2 , & - Spn9RDyb3 , Spn9RDzb1 , Spn9RDzb2 , Spn9RDzb3 , Spn9TDxb1 , Spn9TDxb2 , Spn9TDxb3 , & - Spn9TDyb1 , Spn9TDyb2 , Spn9TDyb3 , Spn9TDzb1 , Spn9TDzb2 , Spn9TDzb3 , TailFurlP , & - TailFurlA , TailFurlP , TailFurlV , TeetAya , TeetPya , TeetPya , TeetVya , & - TFrlBrM , TipClrnc1 , TipClrnc2 , TipClrnc3 , TipALgxb1 , TipALgxb2 , TipALgxb3 , & - TipALgyb1 , TipALgyb2 , TipALgyb3 , TipALgzb1 , TipALgzb2 , TipALgzb3 , TipALxb1 , & - TipALxb2 , TipALxb3 , TipALyb1 , TipALyb2 , TipALyb3 , TipALzb1 , TipALzb2 , & - TipALzb3 , TipClrnc1 , TipClrnc2 , TipClrnc3 , TipDxb1 , TipDxb2 , TipDxb3 , & - TipDxc1 , TipDxc2 , TipDxc3 , TipDyb1 , TipDyb2 , TipDyb3 , TipDyc1 , & - TipDyc2 , TipDyc3 , TipDzc1 , TipDzc2 , TipDzc3 , TipDzc1 , TipDzc2 , & - TipDzc3 , TipRDxb1 , TipRDxb2 , TipRDxb3 , TipRDyb1 , TipRDyb2 , TipRDyb3 , & - TipRDzc1 , TipRDzc2 , TipRDzc3 , TipRDzc1 , TipRDzc2 , TipRDzc3 , YawBrTDzt , & - YawBrTDxt , YawBrRDyt , YawBrRDxt , YawBrTDyt , YawBrRDzt , TwHt1ALgxt , TwHt1ALgyt , & - TwHt1ALgzt , TwHt1ALxt , TwHt1ALyt , TwHt1ALzt , TwHt1FLxt , TwHt1FLyt , TwHt1FLzt , & - TwHt1MLxt , TwHt1MLyt , TwHt1MLzt , TwHt1RDxt , TwHt1RDyt , TwHt1RDzt , TwHt1RPxi , & - TwHt1RPyi , TwHt1RPzi , TwHt1TDxt , TwHt1TDyt , TwHt1TDzt , TwHt1TPxi , TwHt1TPyi , & - TwHt1TPzi , TwHt2ALgxt , TwHt2ALgyt , TwHt2ALgzt , TwHt2ALxt , TwHt2ALyt , TwHt2ALzt , & - TwHt2FLxt , TwHt2FLyt , TwHt2FLzt , TwHt2MLxt , TwHt2MLyt , TwHt2MLzt , TwHt2RDxt , & - TwHt2RDyt , TwHt2RDzt , TwHt2RPxi , TwHt2RPyi , TwHt2RPzi , TwHt2TDxt , TwHt2TDyt , & - TwHt2TDzt , TwHt2TPxi , TwHt2TPyi , TwHt2TPzi , TwHt3ALgxt , TwHt3ALgyt , TwHt3ALgzt , & - TwHt3ALxt , TwHt3ALyt , TwHt3ALzt , TwHt3FLxt , TwHt3FLyt , TwHt3FLzt , TwHt3MLxt , & - TwHt3MLyt , TwHt3MLzt , TwHt3RDxt , TwHt3RDyt , TwHt3RDzt , TwHt3RPxi , TwHt3RPyi , & - TwHt3RPzi , TwHt3TDxt , TwHt3TDyt , TwHt3TDzt , TwHt3TPxi , TwHt3TPyi , TwHt3TPzi , & - TwHt4ALgxt , TwHt4ALgyt , TwHt4ALgzt , TwHt4ALxt , TwHt4ALyt , TwHt4ALzt , TwHt4FLxt , & - TwHt4FLyt , TwHt4FLzt , TwHt4MLxt , TwHt4MLyt , TwHt4MLzt , TwHt4RDxt , TwHt4RDyt , & - TwHt4RDzt , TwHt4RPxi , TwHt4RPyi , TwHt4RPzi , TwHt4TDxt , TwHt4TDyt , TwHt4TDzt , & - TwHt4TPxi , TwHt4TPyi , TwHt4TPzi , TwHt5ALgxt , TwHt5ALgyt , TwHt5ALgzt , TwHt5ALxt , & - TwHt5ALyt , TwHt5ALzt , TwHt5FLxt , TwHt5FLyt , TwHt5FLzt , TwHt5MLxt , TwHt5MLyt , & - TwHt5MLzt , TwHt5RDxt , TwHt5RDyt , TwHt5RDzt , TwHt5RPxi , TwHt5RPyi , TwHt5RPzi , & - TwHt5TDxt , TwHt5TDyt , TwHt5TDzt , TwHt5TPxi , TwHt5TPyi , TwHt5TPzi , TwHt6ALgxt , & - TwHt6ALgyt , TwHt6ALgzt , TwHt6ALxt , TwHt6ALyt , TwHt6ALzt , TwHt6FLxt , TwHt6FLyt , & - TwHt6FLzt , TwHt6MLxt , TwHt6MLyt , TwHt6MLzt , TwHt6RDxt , TwHt6RDyt , TwHt6RDzt , & - TwHt6RPxi , TwHt6RPyi , TwHt6RPzi , TwHt6TDxt , TwHt6TDyt , TwHt6TDzt , TwHt6TPxi , & - TwHt6TPyi , TwHt6TPzi , TwHt7ALgxt , TwHt7ALgyt , TwHt7ALgzt , TwHt7ALxt , TwHt7ALyt , & - TwHt7ALzt , TwHt7FLxt , TwHt7FLyt , TwHt7FLzt , TwHt7MLxt , TwHt7MLyt , TwHt7MLzt , & - TwHt7RDxt , TwHt7RDyt , TwHt7RDzt , TwHt7RPxi , TwHt7RPyi , TwHt7RPzi , TwHt7TDxt , & - TwHt7TDyt , TwHt7TDzt , TwHt7TPxi , TwHt7TPyi , TwHt7TPzi , TwHt8ALgxt , TwHt8ALgyt , & - TwHt8ALgzt , TwHt8ALxt , TwHt8ALyt , TwHt8ALzt , TwHt8FLxt , TwHt8FLyt , TwHt8FLzt , & - TwHt8MLxt , TwHt8MLyt , TwHt8MLzt , TwHt8RDxt , TwHt8RDyt , TwHt8RDzt , TwHt8RPxi , & - TwHt8RPyi , TwHt8RPzi , TwHt8TDxt , TwHt8TDyt , TwHt8TDzt , TwHt8TPxi , TwHt8TPyi , & - TwHt8TPzi , TwHt9ALgxt , TwHt9ALgyt , TwHt9ALgzt , TwHt9ALxt , TwHt9ALyt , TwHt9ALzt , & - TwHt9FLxt , TwHt9FLyt , TwHt9FLzt , TwHt9MLxt , TwHt9MLyt , TwHt9MLzt , TwHt9RDxt , & - TwHt9RDyt , TwHt9RDzt , TwHt9RPxi , TwHt9RPyi , TwHt9RPzi , TwHt9TDxt , TwHt9TDyt , & - TwHt9TDzt , TwHt9TPxi , TwHt9TPyi , TwHt9TPzi , TwrBsFxt , TwrBsFyt , TwrBsFzt , & - TwrBsMxt , TwrBsMyt , TwrBsMzt , TipClrnc1 , TipClrnc2 , TipClrnc3 , TwrTpTDxi , & - TwrTpTDyi , TwrTpTDzi , TipRDzc1 , TipRDzc2 , TipRDzc3 , YawAzn , YawAzn , & - YawAzn , YawBrFxn , YawBrFxp , YawBrFyn , YawBrFyp , YawBrFzn , YawBrFzn , & - YawBrMxn , YawBrMxp , YawBrMyn , YawBrMyp , YawBrMzn , YawBrMzn , YawBrRAxp , & - YawBrRAyp , YawBrRAzp , YawBrRDxt , YawBrRDyt , YawBrRDzt , YawBrRVxp , YawBrRVyp , & - YawBrRVzp , YawBrTAgxp , YawBrTAgyp , YawBrTAgzp , YawBrTAxp , YawBrTAyp , YawBrTAzp , & - TwrTpTDxi , YawBrTDxp , YawBrTDxt , TwrTpTDyi , YawBrTDyp , YawBrTDyt , TwrTpTDzi , & - YawBrTDzp , YawBrTDzt , YawBrTVxp , YawBrTVyp , YawBrTVzp , YawPzn , YawPzn , & - YawPzn , YawVzn , YawVzn , YawVzn /) - CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(1110) = (/ & ! This lists the units corresponding to the allowed parameters + dOmegaYF , HSShftA , HSShftV , HSSBrTq , HSShftA , HSShftPwr , HSShftTq , & + HSShftV , TipDyc1 , TipDyc2 , TipDyc3 , LSSGagAxa , LSSGagAxa , LSSGagAxa , & + LSShftFxa , LSShftFxa , LSShftFya , LSShftFys , LSShftFza , LSShftFzs , LSShftMxa , & + LSShftMxa , LSSGagMya , LSSGagMys , LSSGagMza , LSSGagMzs , LSSGagPxa , LSSGagPxa , & + LSSGagPxa , LSSGagVxa , LSSGagVxa , LSSGagVxa , LSShftFxa , LSShftFxa , LSShftFya , & + LSShftFys , LSShftFza , LSShftFzs , LSShftMxa , LSShftMxa , RotPwr , LSShftMxa , & + LSSTipAxa , LSSTipAxa , LSSTipAxa , LSSTipMya , LSSTipMys , LSSTipMza , LSSTipMzs , & + LSSTipPxa , LSSTipPxa , LSSTipPxa , LSSTipVxa , LSSTipVxa , LSSTipVxa , YawPzn , & + YawAzn , YawPzn , YawVzn , NcIMURAxs , NcIMURAys , NcIMURAzs , NcIMURVxs , & + NcIMURVys , NcIMURVzs , NcIMUTAgxs , NcIMUTAgys , NcIMUTAgzs , NcIMUTAxs , NcIMUTAys , & + NcIMUTAzs , NcIMUTVxs , NcIMUTVys , NcIMUTVzs , OmegaYF , TipDxc1 , TipDxc2 , & + TipDxc3 , TipRDyb1 , TipRDyb2 , TipRDyb3 , PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , & + PtchPMzc1 , PtchPMzc2 , PtchPMzc3 , PtfmTDzi , PtfmRDyi , PtfmRAxi , PtfmRAxt , & + PtfmRAyi , PtfmRAyt , PtfmRAzi , PtfmRAzt , PtfmRDxi , PtfmRDyi , PtfmRDzi , & + PtfmRDxi , PtfmRVxi , PtfmRVxt , PtfmRVyi , PtfmRVyt , PtfmRVzi , PtfmRVzt , & + PtfmTDxi , PtfmTDyi , PtfmTAgxi , PtfmTAgxt , PtfmTAgyi , PtfmTAgyt , PtfmTAgzi , & + PtfmTAgzt , PtfmTAxi , PtfmTAxt , PtfmTAyi , PtfmTAyt , PtfmTAzi , PtfmTAzt , & + PtfmTDxi , PtfmTDxt , PtfmTDyi , PtfmTDyt , PtfmTDzi , PtfmTDzt , PtfmTVxi , & + PtfmTVxt , PtfmTVyi , PtfmTVyt , PtfmTVzi , PtfmTVzt , PtfmRDzi , QD2_B1E1 , & + QD2_B1F1 , QD2_B1F2 , QD2_B2E1 , QD2_B2F1 , QD2_B2F2 , QD2_B3E1 , QD2_B3F1 , & + QD2_B3F2 , QD2_DrTr , QD2_GeAz , QD2_Hv , QD2_P , QD2_R , QD2_RFrl , & + QD2_Sg , QD2_Sw , QD2_Teet , QD2_TFA1 , QD2_TFA2 , QD2_TFrl , QD2_TSS1 , & + QD2_TSS2 , QD2_Y , QD2_Yaw , QD_B1E1 , QD_B1F1 , QD_B1F2 , QD_B2E1 , & + QD_B2F1 , QD_B2F2 , QD_B3E1 , QD_B3F1 , QD_B3F2 , QD_DrTr , QD_GeAz , & + QD_Hv , QD_P , QD_R , QD_RFrl , QD_Sg , QD_Sw , QD_Teet , & + QD_TFA1 , QD_TFA2 , QD_TFrl , QD_TSS1 , QD_TSS2 , QD_Y , QD_Yaw , & + Q_B1E1 , Q_B1F1 , Q_B1F2 , Q_B2E1 , Q_B2F1 , Q_B2F2 , Q_B3E1 , & + Q_B3F1 , Q_B3F2 , Q_DrTr , Q_GeAz , Q_Hv , Q_P , Q_R , & + Q_RFrl , Q_Sg , Q_Sw , Q_Teet , Q_TFA1 , Q_TFA2 , Q_TFrl , & + Q_TSS1 , Q_TSS2 , Q_Y , Q_Yaw , RFrlBrM , TipRDxb1 , TipRDxb2 , & + TipRDxb3 , RootFxb1 , RootFxb2 , RootFxb3 , RootFxc1 , RootFxc2 , RootFxc3 , & + RootFyb1 , RootFyb2 , RootFyb3 , RootFyc1 , RootFyc2 , RootFyc3 , RootFzc1 , & + RootFzc2 , RootFzc3 , RootFzc1 , RootFzc2 , RootFzc3 , RootMxb1 , RootMxb2 , & + RootMxb3 , RootMyb1 , RootMyb2 , RootMyb3 , RootMxc1 , RootMxc2 , RootMxc3 , & + RootMyc1 , RootMyc2 , RootMyc3 , RootMxb1 , RootMxb2 , RootMxb3 , RootMxc1 , & + RootMxc2 , RootMxc3 , RootMyb1 , RootMyb2 , RootMyb3 , RootMyc1 , RootMyc2 , & + RootMyc3 , RootMzc1 , RootMzc2 , RootMzc3 , RootMzc1 , RootMzc2 , RootMzc3 , & + LSSTipAxa , RotFurlP , RotFurlA , RotFurlP , RotFurlV , RotPwr , LSSTipVxa , & + TeetAya , TeetPya , TeetVya , LSShftFxa , LSShftMxa , Spn1ALgxb1 , Spn1ALgxb2 , & + Spn1ALgxb3 , Spn1ALgyb1 , Spn1ALgyb2 , Spn1ALgyb3 , Spn1ALgzb1 , Spn1ALgzb2 , Spn1ALgzb3 , & + Spn1ALxb1 , Spn1ALxb2 , Spn1ALxb3 , Spn1ALyb1 , Spn1ALyb2 , Spn1ALyb3 , Spn1ALzb1 , & + Spn1ALzb2 , Spn1ALzb3 , Spn1FLxb1 , Spn1FLxb2 , Spn1FLxb3 , Spn1FLyb1 , Spn1FLyb2 , & + Spn1FLyb3 , Spn1FLzb1 , Spn1FLzb2 , Spn1FLzb3 , Spn1MLxb1 , Spn1MLxb2 , Spn1MLxb3 , & + Spn1MLyb1 , Spn1MLyb2 , Spn1MLyb3 , Spn1MLzb1 , Spn1MLzb2 , Spn1MLzb3 , Spn1RDxb1 , & + Spn1RDxb2 , Spn1RDxb3 , Spn1RDyb1 , Spn1RDyb2 , Spn1RDyb3 , Spn1RDzb1 , Spn1RDzb2 , & + Spn1RDzb3 , Spn1TDxb1 , Spn1TDxb2 , Spn1TDxb3 , Spn1TDyb1 , Spn1TDyb2 , Spn1TDyb3 , & + Spn1TDzb1 , Spn1TDzb2 , Spn1TDzb3 , Spn2ALgxb1 , Spn2ALgxb2 , Spn2ALgxb3 , Spn2ALgyb1 , & + Spn2ALgyb2 , Spn2ALgyb3 , Spn2ALgzb1 , Spn2ALgzb2 , Spn2ALgzb3 , Spn2ALxb1 , Spn2ALxb2 , & + Spn2ALxb3 , Spn2ALyb1 , Spn2ALyb2 , Spn2ALyb3 , Spn2ALzb1 , Spn2ALzb2 , Spn2ALzb3 , & + Spn2FLxb1 , Spn2FLxb2 , Spn2FLxb3 , Spn2FLyb1 , Spn2FLyb2 , Spn2FLyb3 , Spn2FLzb1 , & + Spn2FLzb2 , Spn2FLzb3 , Spn2MLxb1 , Spn2MLxb2 , Spn2MLxb3 , Spn2MLyb1 , Spn2MLyb2 , & + Spn2MLyb3 , Spn2MLzb1 , Spn2MLzb2 , Spn2MLzb3 , Spn2RDxb1 , Spn2RDxb2 , Spn2RDxb3 , & + Spn2RDyb1 , Spn2RDyb2 , Spn2RDyb3 , Spn2RDzb1 , Spn2RDzb2 , Spn2RDzb3 , Spn2TDxb1 , & + Spn2TDxb2 , Spn2TDxb3 , Spn2TDyb1 , Spn2TDyb2 , Spn2TDyb3 , Spn2TDzb1 , Spn2TDzb2 , & + Spn2TDzb3 , Spn3ALgxb1 , Spn3ALgxb2 , Spn3ALgxb3 , Spn3ALgyb1 , Spn3ALgyb2 , Spn3ALgyb3 , & + Spn3ALgzb1 , Spn3ALgzb2 , Spn3ALgzb3 , Spn3ALxb1 , Spn3ALxb2 , Spn3ALxb3 , Spn3ALyb1 , & + Spn3ALyb2 , Spn3ALyb3 , Spn3ALzb1 , Spn3ALzb2 , Spn3ALzb3 , Spn3FLxb1 , Spn3FLxb2 , & + Spn3FLxb3 , Spn3FLyb1 , Spn3FLyb2 , Spn3FLyb3 , Spn3FLzb1 , Spn3FLzb2 , Spn3FLzb3 , & + Spn3MLxb1 , Spn3MLxb2 , Spn3MLxb3 , Spn3MLyb1 , Spn3MLyb2 , Spn3MLyb3 , Spn3MLzb1 , & + Spn3MLzb2 , Spn3MLzb3 , Spn3RDxb1 , Spn3RDxb2 , Spn3RDxb3 , Spn3RDyb1 , Spn3RDyb2 , & + Spn3RDyb3 , Spn3RDzb1 , Spn3RDzb2 , Spn3RDzb3 , Spn3TDxb1 , Spn3TDxb2 , Spn3TDxb3 , & + Spn3TDyb1 , Spn3TDyb2 , Spn3TDyb3 , Spn3TDzb1 , Spn3TDzb2 , Spn3TDzb3 , Spn4ALgxb1 , & + Spn4ALgxb2 , Spn4ALgxb3 , Spn4ALgyb1 , Spn4ALgyb2 , Spn4ALgyb3 , Spn4ALgzb1 , Spn4ALgzb2 , & + Spn4ALgzb3 , Spn4ALxb1 , Spn4ALxb2 , Spn4ALxb3 , Spn4ALyb1 , Spn4ALyb2 , Spn4ALyb3 , & + Spn4ALzb1 , Spn4ALzb2 , Spn4ALzb3 , Spn4FLxb1 , Spn4FLxb2 , Spn4FLxb3 , Spn4FLyb1 , & + Spn4FLyb2 , Spn4FLyb3 , Spn4FLzb1 , Spn4FLzb2 , Spn4FLzb3 , Spn4MLxb1 , Spn4MLxb2 , & + Spn4MLxb3 , Spn4MLyb1 , Spn4MLyb2 , Spn4MLyb3 , Spn4MLzb1 , Spn4MLzb2 , Spn4MLzb3 , & + Spn4RDxb1 , Spn4RDxb2 , Spn4RDxb3 , Spn4RDyb1 , Spn4RDyb2 , Spn4RDyb3 , Spn4RDzb1 , & + Spn4RDzb2 , Spn4RDzb3 , Spn4TDxb1 , Spn4TDxb2 , Spn4TDxb3 , Spn4TDyb1 , Spn4TDyb2 , & + Spn4TDyb3 , Spn4TDzb1 , Spn4TDzb2 , Spn4TDzb3 , Spn5ALgxb1 , Spn5ALgxb2 , Spn5ALgxb3 , & + Spn5ALgyb1 , Spn5ALgyb2 , Spn5ALgyb3 , Spn5ALgzb1 , Spn5ALgzb2 , Spn5ALgzb3 , Spn5ALxb1 , & + Spn5ALxb2 , Spn5ALxb3 , Spn5ALyb1 , Spn5ALyb2 , Spn5ALyb3 , Spn5ALzb1 , Spn5ALzb2 , & + Spn5ALzb3 , Spn5FLxb1 , Spn5FLxb2 , Spn5FLxb3 , Spn5FLyb1 , Spn5FLyb2 , Spn5FLyb3 , & + Spn5FLzb1 , Spn5FLzb2 , Spn5FLzb3 , Spn5MLxb1 , Spn5MLxb2 , Spn5MLxb3 , Spn5MLyb1 , & + Spn5MLyb2 , Spn5MLyb3 , Spn5MLzb1 , Spn5MLzb2 , Spn5MLzb3 , Spn5RDxb1 , Spn5RDxb2 , & + Spn5RDxb3 , Spn5RDyb1 , Spn5RDyb2 , Spn5RDyb3 , Spn5RDzb1 , Spn5RDzb2 , Spn5RDzb3 , & + Spn5TDxb1 , Spn5TDxb2 , Spn5TDxb3 , Spn5TDyb1 , Spn5TDyb2 , Spn5TDyb3 , Spn5TDzb1 , & + Spn5TDzb2 , Spn5TDzb3 , Spn6ALgxb1 , Spn6ALgxb2 , Spn6ALgxb3 , Spn6ALgyb1 , Spn6ALgyb2 , & + Spn6ALgyb3 , Spn6ALgzb1 , Spn6ALgzb2 , Spn6ALgzb3 , Spn6ALxb1 , Spn6ALxb2 , Spn6ALxb3 , & + Spn6ALyb1 , Spn6ALyb2 , Spn6ALyb3 , Spn6ALzb1 , Spn6ALzb2 , Spn6ALzb3 , Spn6FLxb1 , & + Spn6FLxb2 , Spn6FLxb3 , Spn6FLyb1 , Spn6FLyb2 , Spn6FLyb3 , Spn6FLzb1 , Spn6FLzb2 , & + Spn6FLzb3 , Spn6MLxb1 , Spn6MLxb2 , Spn6MLxb3 , Spn6MLyb1 , Spn6MLyb2 , Spn6MLyb3 , & + Spn6MLzb1 , Spn6MLzb2 , Spn6MLzb3 , Spn6RDxb1 , Spn6RDxb2 , Spn6RDxb3 , Spn6RDyb1 , & + Spn6RDyb2 , Spn6RDyb3 , Spn6RDzb1 , Spn6RDzb2 , Spn6RDzb3 , Spn6TDxb1 , Spn6TDxb2 , & + Spn6TDxb3 , Spn6TDyb1 , Spn6TDyb2 , Spn6TDyb3 , Spn6TDzb1 , Spn6TDzb2 , Spn6TDzb3 , & + Spn7ALgxb1 , Spn7ALgxb2 , Spn7ALgxb3 , Spn7ALgyb1 , Spn7ALgyb2 , Spn7ALgyb3 , Spn7ALgzb1 , & + Spn7ALgzb2 , Spn7ALgzb3 , Spn7ALxb1 , Spn7ALxb2 , Spn7ALxb3 , Spn7ALyb1 , Spn7ALyb2 , & + Spn7ALyb3 , Spn7ALzb1 , Spn7ALzb2 , Spn7ALzb3 , Spn7FLxb1 , Spn7FLxb2 , Spn7FLxb3 , & + Spn7FLyb1 , Spn7FLyb2 , Spn7FLyb3 , Spn7FLzb1 , Spn7FLzb2 , Spn7FLzb3 , Spn7MLxb1 , & + Spn7MLxb2 , Spn7MLxb3 , Spn7MLyb1 , Spn7MLyb2 , Spn7MLyb3 , Spn7MLzb1 , Spn7MLzb2 , & + Spn7MLzb3 , Spn7RDxb1 , Spn7RDxb2 , Spn7RDxb3 , Spn7RDyb1 , Spn7RDyb2 , Spn7RDyb3 , & + Spn7RDzb1 , Spn7RDzb2 , Spn7RDzb3 , Spn7TDxb1 , Spn7TDxb2 , Spn7TDxb3 , Spn7TDyb1 , & + Spn7TDyb2 , Spn7TDyb3 , Spn7TDzb1 , Spn7TDzb2 , Spn7TDzb3 , Spn8ALgxb1 , Spn8ALgxb2 , & + Spn8ALgxb3 , Spn8ALgyb1 , Spn8ALgyb2 , Spn8ALgyb3 , Spn8ALgzb1 , Spn8ALgzb2 , Spn8ALgzb3 , & + Spn8ALxb1 , Spn8ALxb2 , Spn8ALxb3 , Spn8ALyb1 , Spn8ALyb2 , Spn8ALyb3 , Spn8ALzb1 , & + Spn8ALzb2 , Spn8ALzb3 , Spn8FLxb1 , Spn8FLxb2 , Spn8FLxb3 , Spn8FLyb1 , Spn8FLyb2 , & + Spn8FLyb3 , Spn8FLzb1 , Spn8FLzb2 , Spn8FLzb3 , Spn8MLxb1 , Spn8MLxb2 , Spn8MLxb3 , & + Spn8MLyb1 , Spn8MLyb2 , Spn8MLyb3 , Spn8MLzb1 , Spn8MLzb2 , Spn8MLzb3 , Spn8RDxb1 , & + Spn8RDxb2 , Spn8RDxb3 , Spn8RDyb1 , Spn8RDyb2 , Spn8RDyb3 , Spn8RDzb1 , Spn8RDzb2 , & + Spn8RDzb3 , Spn8TDxb1 , Spn8TDxb2 , Spn8TDxb3 , Spn8TDyb1 , Spn8TDyb2 , Spn8TDyb3 , & + Spn8TDzb1 , Spn8TDzb2 , Spn8TDzb3 , Spn9ALgxb1 , Spn9ALgxb2 , Spn9ALgxb3 , Spn9ALgyb1 , & + Spn9ALgyb2 , Spn9ALgyb3 , Spn9ALgzb1 , Spn9ALgzb2 , Spn9ALgzb3 , Spn9ALxb1 , Spn9ALxb2 , & + Spn9ALxb3 , Spn9ALyb1 , Spn9ALyb2 , Spn9ALyb3 , Spn9ALzb1 , Spn9ALzb2 , Spn9ALzb3 , & + Spn9FLxb1 , Spn9FLxb2 , Spn9FLxb3 , Spn9FLyb1 , Spn9FLyb2 , Spn9FLyb3 , Spn9FLzb1 , & + Spn9FLzb2 , Spn9FLzb3 , Spn9MLxb1 , Spn9MLxb2 , Spn9MLxb3 , Spn9MLyb1 , Spn9MLyb2 , & + Spn9MLyb3 , Spn9MLzb1 , Spn9MLzb2 , Spn9MLzb3 , Spn9RDxb1 , Spn9RDxb2 , Spn9RDxb3 , & + Spn9RDyb1 , Spn9RDyb2 , Spn9RDyb3 , Spn9RDzb1 , Spn9RDzb2 , Spn9RDzb3 , Spn9TDxb1 , & + Spn9TDxb2 , Spn9TDxb3 , Spn9TDyb1 , Spn9TDyb2 , Spn9TDyb3 , Spn9TDzb1 , Spn9TDzb2 , & + Spn9TDzb3 , TailFurlP , TailFurlA , TailFurlP , TailFurlV , TeetAya , TeetPya , & + TeetPya , TeetVya , TFrlBrM , TipClrnc1 , TipClrnc2 , TipClrnc3 , TipALgxb1 , & + TipALgxb2 , TipALgxb3 , TipALgyb1 , TipALgyb2 , TipALgyb3 , TipALgzb1 , TipALgzb2 , & + TipALgzb3 , TipALxb1 , TipALxb2 , TipALxb3 , TipALyb1 , TipALyb2 , TipALyb3 , & + TipALzb1 , TipALzb2 , TipALzb3 , TipClrnc1 , TipClrnc2 , TipClrnc3 , TipDxb1 , & + TipDxb2 , TipDxb3 , TipDxc1 , TipDxc2 , TipDxc3 , TipDyb1 , TipDyb2 , & + TipDyb3 , TipDyc1 , TipDyc2 , TipDyc3 , TipDzc1 , TipDzc2 , TipDzc3 , & + TipDzc1 , TipDzc2 , TipDzc3 , TipRDxb1 , TipRDxb2 , TipRDxb3 , TipRDyb1 , & + TipRDyb2 , TipRDyb3 , TipRDzc1 , TipRDzc2 , TipRDzc3 , TipRDzc1 , TipRDzc2 , & + TipRDzc3 , YawBrTDzt , YawBrTDxt , YawBrRDyt , YawBrRDxt , YawBrTDyt , YawBrRDzt , & + TwHt1ALgxt , TwHt1ALgyt , TwHt1ALgzt , TwHt1ALxt , TwHt1ALyt , TwHt1ALzt , TwHt1FLxt , & + TwHt1FLyt , TwHt1FLzt , TwHt1MLxt , TwHt1MLyt , TwHt1MLzt , TwHt1RDxt , TwHt1RDyt , & + TwHt1RDzt , TwHt1RPxi , TwHt1RPyi , TwHt1RPzi , TwHt1TDxt , TwHt1TDyt , TwHt1TDzt , & + TwHt1TPxi , TwHt1TPyi , TwHt1TPzi , TwHt2ALgxt , TwHt2ALgyt , TwHt2ALgzt , TwHt2ALxt , & + TwHt2ALyt , TwHt2ALzt , TwHt2FLxt , TwHt2FLyt , TwHt2FLzt , TwHt2MLxt , TwHt2MLyt , & + TwHt2MLzt , TwHt2RDxt , TwHt2RDyt , TwHt2RDzt , TwHt2RPxi , TwHt2RPyi , TwHt2RPzi , & + TwHt2TDxt , TwHt2TDyt , TwHt2TDzt , TwHt2TPxi , TwHt2TPyi , TwHt2TPzi , TwHt3ALgxt , & + TwHt3ALgyt , TwHt3ALgzt , TwHt3ALxt , TwHt3ALyt , TwHt3ALzt , TwHt3FLxt , TwHt3FLyt , & + TwHt3FLzt , TwHt3MLxt , TwHt3MLyt , TwHt3MLzt , TwHt3RDxt , TwHt3RDyt , TwHt3RDzt , & + TwHt3RPxi , TwHt3RPyi , TwHt3RPzi , TwHt3TDxt , TwHt3TDyt , TwHt3TDzt , TwHt3TPxi , & + TwHt3TPyi , TwHt3TPzi , TwHt4ALgxt , TwHt4ALgyt , TwHt4ALgzt , TwHt4ALxt , TwHt4ALyt , & + TwHt4ALzt , TwHt4FLxt , TwHt4FLyt , TwHt4FLzt , TwHt4MLxt , TwHt4MLyt , TwHt4MLzt , & + TwHt4RDxt , TwHt4RDyt , TwHt4RDzt , TwHt4RPxi , TwHt4RPyi , TwHt4RPzi , TwHt4TDxt , & + TwHt4TDyt , TwHt4TDzt , TwHt4TPxi , TwHt4TPyi , TwHt4TPzi , TwHt5ALgxt , TwHt5ALgyt , & + TwHt5ALgzt , TwHt5ALxt , TwHt5ALyt , TwHt5ALzt , TwHt5FLxt , TwHt5FLyt , TwHt5FLzt , & + TwHt5MLxt , TwHt5MLyt , TwHt5MLzt , TwHt5RDxt , TwHt5RDyt , TwHt5RDzt , TwHt5RPxi , & + TwHt5RPyi , TwHt5RPzi , TwHt5TDxt , TwHt5TDyt , TwHt5TDzt , TwHt5TPxi , TwHt5TPyi , & + TwHt5TPzi , TwHt6ALgxt , TwHt6ALgyt , TwHt6ALgzt , TwHt6ALxt , TwHt6ALyt , TwHt6ALzt , & + TwHt6FLxt , TwHt6FLyt , TwHt6FLzt , TwHt6MLxt , TwHt6MLyt , TwHt6MLzt , TwHt6RDxt , & + TwHt6RDyt , TwHt6RDzt , TwHt6RPxi , TwHt6RPyi , TwHt6RPzi , TwHt6TDxt , TwHt6TDyt , & + TwHt6TDzt , TwHt6TPxi , TwHt6TPyi , TwHt6TPzi , TwHt7ALgxt , TwHt7ALgyt , TwHt7ALgzt , & + TwHt7ALxt , TwHt7ALyt , TwHt7ALzt , TwHt7FLxt , TwHt7FLyt , TwHt7FLzt , TwHt7MLxt , & + TwHt7MLyt , TwHt7MLzt , TwHt7RDxt , TwHt7RDyt , TwHt7RDzt , TwHt7RPxi , TwHt7RPyi , & + TwHt7RPzi , TwHt7TDxt , TwHt7TDyt , TwHt7TDzt , TwHt7TPxi , TwHt7TPyi , TwHt7TPzi , & + TwHt8ALgxt , TwHt8ALgyt , TwHt8ALgzt , TwHt8ALxt , TwHt8ALyt , TwHt8ALzt , TwHt8FLxt , & + TwHt8FLyt , TwHt8FLzt , TwHt8MLxt , TwHt8MLyt , TwHt8MLzt , TwHt8RDxt , TwHt8RDyt , & + TwHt8RDzt , TwHt8RPxi , TwHt8RPyi , TwHt8RPzi , TwHt8TDxt , TwHt8TDyt , TwHt8TDzt , & + TwHt8TPxi , TwHt8TPyi , TwHt8TPzi , TwHt9ALgxt , TwHt9ALgyt , TwHt9ALgzt , TwHt9ALxt , & + TwHt9ALyt , TwHt9ALzt , TwHt9FLxt , TwHt9FLyt , TwHt9FLzt , TwHt9MLxt , TwHt9MLyt , & + TwHt9MLzt , TwHt9RDxt , TwHt9RDyt , TwHt9RDzt , TwHt9RPxi , TwHt9RPyi , TwHt9RPzi , & + TwHt9TDxt , TwHt9TDyt , TwHt9TDzt , TwHt9TPxi , TwHt9TPyi , TwHt9TPzi , TwrBsFxt , & + TwrBsFyt , TwrBsFzt , TwrBsMxt , TwrBsMyt , TwrBsMzt , TipClrnc1 , TipClrnc2 , & + TipClrnc3 , TwrTpTDxi , TwrTpTDyi , TwrTpTDzi , TipRDzc1 , TipRDzc2 , TipRDzc3 , & + YawAzn , YawAzn , YawAzn , YawBrFxn , YawBrFxp , YawBrFyn , YawBrFyp , & + YawBrFzn , YawBrFzn , YawBrMxn , YawBrMxp , YawBrMyn , YawBrMyp , YawBrMzn , & + YawBrMzn , YawBrRAxp , YawBrRAyp , YawBrRAzp , YawBrRDxt , YawBrRDyt , YawBrRDzt , & + YawBrRVxp , YawBrRVyp , YawBrRVzp , YawBrTAgxp , YawBrTAgyp , YawBrTAgzp , YawBrTAxp , & + YawBrTAyp , YawBrTAzp , TwrTpTDxi , YawBrTDxp , YawBrTDxt , TwrTpTDyi , YawBrTDyp , & + YawBrTDyt , TwrTpTDzi , YawBrTDzp , YawBrTDzt , YawBrTVxp , YawBrTVyp , YawBrTVzp , & + YawFriMfp , YawFriMom , YawFriMz , YawPzn , YawPzn , YawPzn , YawVzn , & + YawVzn , YawVzn /) + CHARACTER(ChanLen), PARAMETER :: ParamUnitsAry(1115) = (/ character(ChanLen) :: & ! This lists the units corresponding to the allowed parameters "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & - "(deg/s^2)","(rpm) ","(kN-m) ","(deg/s^2)","(kW) ","(kN-m) ","(rpm) ", & - "(m) ","(m) ","(m) ","(deg/s^2)","(deg/s^2)","(deg/s^2)","(kN) ", & - "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ", & - "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ", & - "(rpm) ","(rpm) ","(rpm) ","(kN) ","(kN) ","(kN) ","(kN) ", & - "(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kW) ","(kN-m) ","(deg/s^2)", & - "(deg/s^2)","(deg/s^2)","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & - "(deg) ","(deg) ","(rpm) ","(rpm) ","(rpm) ","(deg) ","(deg/s^2)", & - "(deg) ","(deg/s) ","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s) ","(deg/s) ", & - "(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s) ","(m/s) ","(m/s) ","(m) ","(m) ","(m) ","(deg) ", & - "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & - "(deg) ","(m) ","(deg) ","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s^2)", & - "(deg/s^2)","(deg/s^2)","(deg) ","(deg) ","(deg) ","(deg) ","(deg/s) ", & - "(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(m) ","(m) ", & + "(deg/s^2)","(deg/s^2)","(rpm) ","(kN-m) ","(deg/s^2)","(kW) ","(kN-m) ", & + "(rpm) ","(m) ","(m) ","(m) ","(deg/s^2)","(deg/s^2)","(deg/s^2)", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ", & + "(deg) ","(rpm) ","(rpm) ","(rpm) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kW) ","(kN-m) ", & + "(deg/s^2)","(deg/s^2)","(deg/s^2)","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(deg) ","(deg) ","(deg) ","(rpm) ","(rpm) ","(rpm) ","(deg) ", & + "(deg/s^2)","(deg) ","(deg/s) ","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s) ", & + "(deg/s) ","(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s) ","(m/s) ","(m/s) ","(deg/s) ","(m) ","(m) ", & + "(m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(m) ","(deg) ","(deg/s^2)","(deg/s^2)", & + "(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ","(deg/s) ", & + "(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ", & - "(m) ","(m) ","(m) ","(m) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(deg) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(rad/s^2)", & - "(rad/s^2)","(m/s^2) ","(rad/s^2)","(rad/s^2)","(rad/s^2)","(m/s^2) ","(m/s^2) ", & - "(rad/s^2)","(m/s^2) ","(m/s^2) ","(rad/s^2)","(m/s^2) ","(m/s^2) ","(rad/s^2)", & - "(rad/s^2)","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & - "(m/s) ","(m/s) ","(m/s) ","(rad/s) ","(rad/s) ","(m/s) ","(rad/s) ", & - "(rad/s) ","(rad/s) ","(m/s) ","(m/s) ","(rad/s) ","(m/s) ","(m/s) ", & - "(rad/s) ","(m/s) ","(m/s) ","(rad/s) ","(rad/s) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(deg) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(rad/s^2)","(rad/s^2)","(m/s^2) ","(rad/s^2)","(rad/s^2)","(rad/s^2)", & + "(m/s^2) ","(m/s^2) ","(rad/s^2)","(m/s^2) ","(m/s^2) ","(rad/s^2)","(m/s^2) ", & + "(m/s^2) ","(rad/s^2)","(rad/s^2)","(m/s) ","(m/s) ","(m/s) ","(m/s) ", & + "(m/s) ","(m/s) ","(m/s) ","(m/s) ","(m/s) ","(rad/s) ","(rad/s) ", & + "(m/s) ","(rad/s) ","(rad/s) ","(rad/s) ","(m/s) ","(m/s) ","(rad/s) ", & + "(m/s) ","(m/s) ","(rad/s) ","(m/s) ","(m/s) ","(rad/s) ","(rad/s) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & - "(rad) ","(rad) ","(m) ","(rad) ","(rad) ","(rad) ","(m) ", & - "(m) ","(rad) ","(m) ","(m) ","(rad) ","(m) ","(m) ", & - "(rad) ","(rad) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(kN) ", & - "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(m) ","(m) ","(rad) ","(rad) ","(m) ","(rad) ","(rad) ", & + "(rad) ","(m) ","(m) ","(rad) ","(m) ","(m) ","(rad) ", & + "(m) ","(m) ","(rad) ","(rad) ","(kN-m) ","(deg) ","(deg) ", & + "(deg) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & - "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ", & "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & - "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg/s^2)","(deg) ", & - "(deg/s^2)","(deg) ","(deg/s) ","(kW) ","(rpm) ","(deg/s^2)","(deg) ", & - "(deg/s) ","(kN) ","(kN-m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(deg/s^2)","(deg) ","(deg/s^2)","(deg) ","(deg/s) ","(kW) ","(rpm) ", & + "(deg/s^2)","(deg) ","(deg/s) ","(kN) ","(kN-m) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & @@ -4373,34 +4404,16 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ", & "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & - "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m) ","(deg) ","(deg/s^2)","(deg) ","(deg/s) ","(deg/s^2)","(deg) ", & + "(deg) ","(deg/s) ","(kN-m) ","(m) ","(m) ","(m) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ", & - "(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & - "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & - "(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & - "(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ","(m) ", & - "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(deg) ", & - "(deg/s^2)","(deg) ","(deg/s) ","(deg/s^2)","(deg) ","(deg) ","(deg/s) ", & - "(kN-m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & - "(m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & - "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ", & - "(m) ","(deg) ","(deg) ","(m) ","(deg) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ", & - "(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ", & - "(deg) ","(deg) ","(m) ","(m) ","(m) ","(m) ","(m) ", & - "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & - "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & - "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN-m) ", & - "(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & - "(deg) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(m) ","(m) ","(deg) ","(deg) ","(m) ","(deg) ", & "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ", & "(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ", & "(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ","(m) ", & @@ -4421,16 +4434,27 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) "(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & "(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ", & "(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ", & - "(m) ","(m) ","(m) ","(m) ","(kN) ","(kN) ","(kN) ", & - "(kN-m) ","(kN-m) ","(kN-m) ","(m) ","(m) ","(m) ","(m) ", & - "(m) ","(m) ","(deg) ","(deg) ","(deg) ","(deg/s^2)","(deg/s^2)", & - "(deg/s^2)","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ","(kN) ", & - "(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg/s^2)", & - "(deg/s^2)","(deg/s^2)","(deg) ","(deg) ","(deg) ","(deg/s) ","(deg/s) ", & - "(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & - "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & - "(m) ","(m) ","(m/s) ","(m/s) ","(m/s) ","(deg) ","(deg) ", & - "(deg) ","(deg/s) ","(deg/s) ","(deg/s) "/) + "(m) ","(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN-m) ", & + "(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(deg) ","(m) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(kN) ", & + "(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ", & + "(deg) ","(deg) ","(deg) ","(deg) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(kN) ","(kN) ","(kN) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ","(deg) ", & + "(m) ","(m) ","(m) ","(m) ","(m) ","(m) ","(kN) ", & + "(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(deg) ","(deg) ","(deg) ", & + "(deg/s^2)","(deg/s^2)","(deg/s^2)","(kN) ","(kN) ","(kN) ","(kN) ", & + "(kN) ","(kN) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ","(kN-m) ", & + "(kN-m) ","(deg/s^2)","(deg/s^2)","(deg/s^2)","(deg) ","(deg) ","(deg) ", & + "(deg/s) ","(deg/s) ","(deg/s) ","(m/s^2) ","(m/s^2) ","(m/s^2) ","(m/s^2) ", & + "(m/s^2) ","(m/s^2) ","(m) ","(m) ","(m) ","(m) ","(m) ", & + "(m) ","(m) ","(m) ","(m) ","(m/s) ","(m/s) ","(m/s) ", & + "(kN-m) ","(kN-m) ","(kN-m) ","(deg) ","(deg) ","(deg) ","(deg/s) ", & + "(deg/s) ","(deg/s) "/) ! Initialize values @@ -4704,17 +4728,18 @@ SUBROUTINE SetOutParam(OutList, p, ErrStat, ErrMsg ) p%OutParam(I)%Indx = 0 ! pick any valid channel (I just picked "Time=0" here because it's universal) p%OutParam(I)%Units = "INVALID" p%OutParam(I)%SignM = 0 ! multiply all results by zero - + CALL SetErrStat(ErrID_Fatal, TRIM(p%OutParam(I)%Name)//" is not an available output channel.",ErrStat,ErrMsg,RoutineName) END IF - + END DO - + RETURN END SUBROUTINE SetOutParam !---------------------------------------------------------------------------------------------------------------------------------- !End of code generated by Matlab script !********************************************************************************************************************************** + !> This routine is used to compute rotor (blade and hub) properties: !! KBF(), KBE(), CBF(), CBE(), FreqBF(), FreqBE(), AxRedBld(), !! TwistedSF(), BldMass(), FirstMom(), SecondMom(), BldCG(), @@ -6591,6 +6616,62 @@ SUBROUTINE Teeter( t, p, TeetDef, TeetRate, TeetMom ) RETURN END SUBROUTINE Teeter !---------------------------------------------------------------------------------------------------------------------------------- +!> This routine computes the Yaw Friction Torque due to yaw rate and acceleration. +SUBROUTINE YawFriction( t, p, Fz, Mzz, Omg, OmgDot, YawFriMf ) +!.................................................................................................................................. + + ! Passed Variables: + REAL(DbKi), INTENT(IN) :: t !< simulation time + TYPE(ED_ParameterType), INTENT(IN) :: p !< parameters from the structural dynamics module + REAL(R8Ki), INTENT(IN ) :: Fz, Mzz !< Effective yaw bearing force and external yaw bearing torque + REAL(R8Ki), INTENT(IN ) :: Omg !< The yaw rate (rotational speed), x%QDT(DOF_Yaw). + REAL(R8Ki), INTENT(IN ) :: OmgDot !< The yaw acceleration (derivative of rotational speed), x%QD2T(DOF_Yaw). + + REAL(ReKi), INTENT(OUT) :: YawFriMf !< The total friction torque (Coulomb + viscous). + + ! Local variables: + REAL(ReKi) :: temp ! It takes teh value of Fz or -1. + + + SELECT CASE ( p%YawFrctMod ) + ! Yaw-friction model {0: none, 1: does not use Fz at yaw bearing, 2: does, 3: user defined model} (switch) + + CASE ( 0_IntKi ) ! None! + + + YawFriMf = 0.0_ReKi + + + CASE ( 1_IntKi, 2_IntKi ) ! 1= no Fz use. 2=Fz used + + temp = -1.0_ReKi !In the case of YawFrctMod=1 + + IF (p%YawFrctMod .EQ. 2) THEN + temp = MIN(0.0_R8Ki, Fz) !In the case of YawFrctMod=2 + ENDIF + + IF (EqualRealNos( Omg, 0.0_R8Ki ) )THEN + YawFriMf = -MIN(real(p%M_CD,ReKi) * ABS(temp), ABS(real(Mzz,ReKi))) * SIGN(1.0_ReKi, real(Mzz,ReKi)) + IF (EqualRealNos( OmgDot, 0.0_R8Ki )) THEN + YawFriMf = -MIN(real(p%M_CSmax,ReKi) * ABS(temp), ABS(real(Mzz,ReKi))) * SIGN(1.0_ReKi, real(Mzz,ReKi)) + ENDIF + ELSE + YawFriMf = real(p%M_CD,ReKi) * temp * sign(1.0_ReKi, real(Omg,ReKi)) - real(p%sig_v,ReKi) * real(Omg,ReKi) + ENDIF + + + CASE ( 3_IntKi ) ! User-defined YawFriMf model. >>>> NOT IMPLEMENTED YET + + + CALL UserYawFrict ( t, Fz, Mzz, Omg, OmgDot, p%RootName, YawFriMf ) + + + END SELECT + + + RETURN +END SUBROUTINE YawFriction +!---------------------------------------------------------------------------------------------------------------------------------- !> This routine computes the tail-furl moment due to tail-furl deflection and rate. SUBROUTINE TFurling( t, p, TFrlDef, TFrlRate, TFrlMom ) ! Passed Variables: @@ -8463,7 +8544,7 @@ SUBROUTINE FillAugMat( p, x, CoordSys, u, HSSBrTrq, RtHSdat, AugMat ) AugMat(p%DOFs%SrtPS(I),DOF_Yaw ) = -DOT_PRODUCT( RtHSdat%PAngVelEN(DOF_Yaw ,0,:), RtHSdat%PMomBNcRt(:,p%DOFs%SrtPS(I)) ) ! [C(q,t)]N + [C(q,t)]R + [C(q,t)]G + [C(q,t)]H + [C(q,t)]B + [C(q,t)]A ENDDO ! I - All active (enabled) DOFs on or below the diagonal AugMat(DOF_Yaw , p%NAug) = DOT_PRODUCT( RtHSdat%PAngVelEN(DOF_Yaw ,0,:), RtHSdat%MomBNcRtt ) & ! {-f(qd,q,t)}N + {-f(qd,q,t)}GravN + {-f(qd,q,t)}R + {-f(qd,q,t)}GravR + {-f(qd,q,t)}G + {-f(qd,q,t)}H + {-f(qd,q,t)}GravH + {-f(qd,q,t)}B + {-f(qd,q,t)}GravB + {-f(qd,q,t)}AeroB + {-f(qd,q,t)}A + {-f(qd,q,t)}GravA + {-f(qd,q,t)}AeroA - + u%YawMom ! + {-f(qd,q,t)}SpringYaw + {-f(qd,q,t)}DampYaw; NOTE: The neutral yaw rate, YawRateNeut, defaults to zero. It is only used for yaw control. + + u%YawMom + RtHSdat%YawFriMom ! + {-f(qd,q,t)}SpringYaw + {-f(qd,q,t)}DampYaw; NOTE: The neutral yaw rate, YawRateNeut, defaults to zero. It is only used for yaw control. ENDIF @@ -9659,6 +9740,8 @@ SUBROUTINE ED_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg END IF OtherState%HSSBrTrq = OtherState%HSSBrTrqC OtherState%SgnPrvLSTQ = OtherState%SgnLSTQ(OtherState%IC(2)) + OtherState%OmegaTn = x%QDT(DOF_Yaw) !this is equal to x%QDT(DOF_Yaw) + OtherState%OmegaDotTn = m%QD2T(DOF_Yaw) !this is equal to m%QD2T(DOF_Yaw) CALL ED_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, ErrStat2, ErrMsg2 ) CALL CheckError(ErrStat2,ErrMsg2) @@ -9693,6 +9776,11 @@ SUBROUTINE ED_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg CALL FixHSSBrTq ( 'P', p, x, OtherState, m, ErrStat2, ErrMsg2 ) CALL CheckError(ErrStat2,ErrMsg2) IF ( ErrStat >= AbortErrLev ) RETURN + + CALL FixYawFric ( 'P', p, x, OtherState, m, ErrStat2, ErrMsg2 ) !KBF Make sure YawFric will not reverse nacelle direction x%qdt(dof_yaw) = OtherState%xdot(OtherState%IC(1))%qt(DOF_Yaw ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + endif @@ -9852,6 +9940,11 @@ SUBROUTINE ED_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, ErrStat, ErrMsg CALL FixHSSBrTq ( 'C', p, x, OtherState, m, ErrStat2, ErrMsg2 ) CALL CheckError(ErrStat2,ErrMsg2) IF ( ErrStat >= AbortErrLev ) RETURN + + CALL FixYawFric ( 'C', p, x, OtherState, m, ErrStat2, ErrMsg2 ) !KBF Make sure YawFric will not reverse nacelle direction x%qdt(dof_yaw) = OtherState%xdot(OtherState%IC(1))%qt(DOF_Yaw ) + CALL CheckError(ErrStat2,ErrMsg2) + IF ( ErrStat >= AbortErrLev ) RETURN + OtherState%SgnPrvLSTQ = SignLSSTrq(p, m) OtherState%SgnLSTQ(OtherState%IC(1)) = OtherState%SgnPrvLSTQ @@ -10330,6 +10423,201 @@ SUBROUTINE FixHSSBrTq ( Integrator, p, x, OtherState, m, ErrStat, ErrMsg ) RETURN END SUBROUTINE FixHSSBrTq +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is used to adjust the YawFricMom value for unphysicalities. +SUBROUTINE FixYawFric ( Integrator, p, x, OtherState, m, ErrStat, ErrMsg ) + + ! Passed variables: + + TYPE(ED_ParameterType), INTENT(IN ) :: p !< Parameters of the structural dynamics module + TYPE(ED_OtherStateType), INTENT(INOUT) :: OtherState !< Other states of the structural dynamics module + TYPE(ED_MiscVarType), INTENT(INOUT) :: m !< misc (optimization) variables + TYPE(ED_ContinuousStateType),INTENT(INOUT) :: x !< Continuous states of the structural dynamics module at n+1 + CHARACTER(1), INTENT(IN ) :: Integrator !< A string holding the current integrator being used. + INTEGER(IntKi), INTENT( OUT) :: ErrStat !< Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None + + + ! Local variables: + + REAL(ReKi) :: RqdFrcYaw ! The force term required to produce RqdQD2Yaw. + REAL(ReKi) :: RqdQD2Yaw ! The required QD2T(DOF_Yaw) to cause the yaw bearing to stop rotating. + + INTEGER :: I ! Loops through all DOFs. + INTEGER(IntKi) :: ErrStat2 + CHARACTER(ErrMsgLen) :: ErrMsg2 + CHARACTER(*), PARAMETER :: RoutineName = 'FixYawFric' + + + + ErrStat = ErrID_None + ErrMsg = "" + + IF ( .NOT. p%DOF_Flag(DOF_Yaw) .OR. EqualRealNos(m%RtHS%YawFriMom, 0.0_ReKi ) ) RETURN + + + ! The absolute magnitude of the yaw friction must have been too great + ! that the yaw speed sign was reversed. What should have happened + ! is that the yaw system should have stopped rotating. In other words, + ! QD(DOF_Yaw,IC(NMX)) should equal zero! Determining what + ! QD2T(DOF_Yaw) will make QD(DOF_Yaw,IC(NMX)) = 0, depends on + ! which integrator we are using. + + + SELECT CASE (Integrator) + + CASE ('C') ! Corrector + + ! Find the required QD2T(DOF_Yaw) to cause the yaw system to stop rotating (RqdQD2Yaw). + ! This is found by solving the corrector formula for QD2(DOF_Yaw,IC(NMX)) + ! when QD(DOF_Yaw,IC(NMX)) equals zero. + + RqdQD2Yaw = ( - OtherState%xdot(OtherState%IC(1))%qt(DOF_Yaw)/ p%DT24 & + - 19.0*OtherState%xdot(OtherState%IC(1))%qdt(DOF_Yaw) & + + 5.0*OtherState%xdot(OtherState%IC(2))%qdt(DOF_Yaw) & + - OtherState%xdot(OtherState%IC(3))%qdt(DOF_Yaw) ) / 9.0 + + CASE ('P') ! Predictor + + ! Find the required QD2T(DOF_Yaw) to cause the yaw system to stop rotating (RqdQD2Yaw). + ! This is found by solving the predictor formula for QD2(DOF_Yaw,IC(1)) + ! when QD(DOF_Yaw,IC(NMX)) equals zero. + + RqdQD2Yaw = ( - OtherState%xdot(OtherState%IC(1))%qt( DOF_Yaw) / p%DT24 & + + 59.0*OtherState%xdot(OtherState%IC(2))%qdt(DOF_Yaw) & + - 37.0*OtherState%xdot(OtherState%IC(3))%qdt(DOF_Yaw) & + + 9.0*OtherState%xdot(OtherState%IC(4))%qdt(DOF_Yaw) )/55.0 + + END SELECT + + + ! Rearrange the augmented matrix of equations of motion to account + ! for the known acceleration of the yaw DOF. To + ! do this, make the known inertia like an applied force to the + ! system. Then set force QD2T(DOF_Yaw) to equal the known + ! acceleration in the augmented matrix of equations of motion: + ! Here is how the new equations are derived. First partition the + ! augmented matrix as follows, where Qa are the unknown + ! accelerations, Qb are the known accelerations, Fa are the + ! known forces, and Fb are the unknown forces: + ! [Caa Cab]{Qa}={Fa} + ! [Cba Cbb]{Qb}={Fb} + ! By rearranging, the equations for the unknown and known + ! accelerations are as follows: + ! [Caa]{Qa}={Fa}-[Cab]{Qb} and [I]{Qb}={Qb} + ! Combining these two sets of equations into one set yields: + ! [Caa 0]{Qa}={{Fa}-[Cab]{Qb}} + ! [ 0 I]{Qb}={ {Qb}} + ! Once this equation is solved, the unknown force can be found from: + ! {Fb}=[Cba]{Qa}+[Cbb]{Qb} + + m%OgnlYawRow = m%AugMat(DOF_Yaw,:) ! copy this row before modifying the old matrix + + + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + + m%AugMat(p%DOFs%SrtPS(I), p%NAUG) = m%AugMat(p%DOFs%SrtPS(I),p%NAUG) & + - m%AugMat(p%DOFs%SrtPS(I),DOF_Yaw)*RqdQD2Yaw ! {{Fa}-[Cab]{Qb}} + m%AugMat(p%DOFs%SrtPS(I),DOF_Yaw) = 0.0 ! [0] + m%AugMat(DOF_Yaw, p%DOFs%SrtPS(I)) = 0.0 ! [0] + + ENDDO ! I - All active (enabled) DOFs + + m%AugMat(DOF_Yaw,DOF_Yaw) = 1.0 ! [I]{Qb}={Qb} + m%AugMat(DOF_Yaw, p%NAUG) = RqdQD2Yaw ! + + + ! Invert the matrix to solve for the new (updated) accelerations. Like in + ! CalcContStateDeriv(), the accelerations are returned by Gauss() in the first NActvDOF + ! elements of the solution vector, SolnVec(). These are transfered to the + ! proper index locations of the acceleration vector QD2T() using the + ! vector subscript array SrtPS(), after Gauss() has been called: + + ! Invert the matrix to solve for the accelerations. The accelerations are returned by Gauss() in the first NActvDOF elements + ! of the solution vector, SolnVec(). These are transfered to the proper index locations of the acceleration vector QD2T() + ! using the vector subscript array SrtPS(), after Gauss() has been called: + + m%AugMat_factor = m%AugMat( p%DOFs%SrtPS( 1:p%DOFs%NActvDOF ), p%DOFs%SrtPSNAUG(1:p%DOFs%NActvDOF) ) + m%SolnVec = m%AugMat( p%DOFs%SrtPS( 1:p%DOFs%NActvDOF ), p%DOFs%SrtPSNAUG(1+p%DOFs%NActvDOF) ) + + CALL LAPACK_getrf( M=p%DOFs%NActvDOF, N=p%DOFs%NActvDOF, A=m%AugMat_factor, IPIV=m%AugMat_pivot, ErrStat=ErrStat2, ErrMsg=ErrMsg2 ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF ( ErrStat >= AbortErrLev ) RETURN + + CALL LAPACK_getrs( TRANS='N',N=p%DOFs%NActvDOF, A=m%AugMat_factor,IPIV=m%AugMat_pivot, B=m%SolnVec, ErrStat=ErrStat2, ErrMsg=ErrMsg2) + + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) RETURN + + + ! Find the force required to produce RqdQD2Yaw from the equations of + ! motion using the new accelerations: + + RqdFrcYaw = 0.0 + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + ! bjj: use m%SolnVec(I) instead of m%QD2T(p%DOFs%SrtPS(I)) here; then update m%QD2T(p%DOFs%SrtPS(I)) + ! later if necessary + RqdFrcYaw = RqdFrcYaw + m%OgnlYawRow(p%DOFs%SrtPS(I))*m%SolnVec(I) ! {Fb}=[Cba]{Qa}+[Cbb]{Qb} (note that [Cba , Cbb] is the old row, and [Qa;Qb] is a single vector SolVec; %Note this is supposedly= YawFriMz+YawFriMf+DeltaM + ENDDO ! I - All active (enabled) DOFs + + ! Find the YawFriMfp necessary to bring about this force, i.e. to stop the yaw: + + OtherState%YawFriMfp = m%RtHs%YawFriMom - ( m%OgnlYawRow(p%NAUG) - RqdFrcYaw ) !This should return YawFriMf - (YawFriMz + YawFriMf - (YawFriMz + YawFriMf + deltaM)) = YawFriMf+DeltaM =YawFriMfp + + OtherState%Mfhat = ABS(OtherState%YawFriMfp) * SIGN(1.0_ReKi, real(m%RtHs%YawFriMom,ReKi)) !Mfhat should have same sign as YawFriMom (YawFriMf) + +!Now check if YawFriMfp is unphysical (i.e., it turned out aligned with omega), and then pick the minimum between YawFriMf and YawFriMfp + + IF ( ABS( OtherState%YawFriMfp ) > ABS( m%RtHs%YawFriMom )) THEN + + OtherState%Mfhat = m%RtHs%YawFriMom !OtherState%HSSBrTrqC = SIGN( u%HSSBrTrqC, x%QDT(DOF_GeAz) ) KBF CHECK THIS, does YawFriMfp need to be OtherState? + + ELSE + + ! overwrite QD2T with the new values + m%QD2T = 0.0 + DO I = 1,p%DOFs%NActvDOF ! Loop through all active (enabled) DOFs + m%QD2T(p%DOFs%SrtPS(I)) = m%SolnVec(I) + ENDDO ! I - All active (enabled) DOFs + + + ! Use the new accelerations to update the DOF values. Again, this + ! depends on the integrator type: + + SELECT CASE (Integrator) + + CASE ('C') ! Corrector + + ! Update QD and QD2 with the new accelerations using the corrector. + ! This will make QD(DOF_Yaw,IC(NMX)) equal to zero and adjust all + ! of the other QDs as necessary. + ! The Q's are unnaffected by this change. + + x%qdt = OtherState%xdot(OtherState%IC(1))%qt & ! qd at n + + p%DT24 * ( 9. * m%QD2T & ! the value we just changed + + 19. * OtherState%xdot(OtherState%IC(1))%qdt & + - 5. * OtherState%xdot(OtherState%IC(2))%qdt & + + 1. * OtherState%xdot(OtherState%IC(3))%qdt ) + + CASE ('P') ! Predictor + + ! Update QD and QD2 with the new accelerations using predictor. + + x%qdt = OtherState%xdot(OtherState%IC(1))%qt + & ! qd at n + p%DT24 * ( 55.*m%QD2T & ! the value we just changed + - 59.*OtherState%xdot(OtherState%IC(2))%qdt & + + 37.*OtherState%xdot(OtherState%IC(3))%qdt & + - 9.*OtherState%xdot(OtherState%IC(4))%qdt ) + + OtherState%xdot ( OtherState%IC(1) )%qdt = m%QD2T ! fix the history + + END SELECT + + ENDIF + + RETURN +END SUBROUTINE FixYawFric + !---------------------------------------------------------------------------------------------------------------------------------- !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/modules/elastodyn/src/ElastoDyn_IO.f90 b/modules/elastodyn/src/ElastoDyn_IO.f90 index e2be81b8a3..5a92da55b8 100644 --- a/modules/elastodyn/src/ElastoDyn_IO.f90 +++ b/modules/elastodyn/src/ElastoDyn_IO.f90 @@ -101,7 +101,13 @@ MODULE ElastoDyn_Parameters ! using the parameters listed in the "OutListParameters.xlsx" Excel file. Any changes to these ! lines should be modified in the Matlab script and/or Excel worksheet as necessary. ! =================================================================================================== -! This code was generated by Write_ChckOutLst.m at 25-Jan-2021 13:23:51. +! This code was generated by "Write_ChckOutLst.m". +!MODULE ElastoDyn_IO_Params +! +! USE NWTC_Library +! USE ElastoDyn_Types +! +! IMPLICIT NONE ! Indices for computing output channels: @@ -111,7 +117,7 @@ MODULE ElastoDyn_Parameters ! Time: - INTEGER(IntKi), PARAMETER :: Time = 0 + INTEGER(IntKi), PARAMETER :: Time = 0 ! Blade 1 Tip Motions: @@ -1083,159 +1089,167 @@ MODULE ElastoDyn_Parameters INTEGER(IntKi), PARAMETER :: YawBrMyp = 857 + ! Yaw Friction: + + INTEGER(IntKi), PARAMETER :: YawFriMom = 858 + INTEGER(IntKi), PARAMETER :: YawFriMfp = 859 + INTEGER(IntKi), PARAMETER :: YawFriMz = 860 + INTEGER(IntKi), PARAMETER :: OmegaYF = 861 + INTEGER(IntKi), PARAMETER :: dOmegaYF = 862 + + ! Tower Base Loads: - INTEGER(IntKi), PARAMETER :: TwrBsFxt = 858 - INTEGER(IntKi), PARAMETER :: TwrBsFyt = 859 - INTEGER(IntKi), PARAMETER :: TwrBsFzt = 860 - INTEGER(IntKi), PARAMETER :: TwrBsMxt = 861 - INTEGER(IntKi), PARAMETER :: TwrBsMyt = 862 - INTEGER(IntKi), PARAMETER :: TwrBsMzt = 863 + INTEGER(IntKi), PARAMETER :: TwrBsFxt = 863 + INTEGER(IntKi), PARAMETER :: TwrBsFyt = 864 + INTEGER(IntKi), PARAMETER :: TwrBsFzt = 865 + INTEGER(IntKi), PARAMETER :: TwrBsMxt = 866 + INTEGER(IntKi), PARAMETER :: TwrBsMyt = 867 + INTEGER(IntKi), PARAMETER :: TwrBsMzt = 868 ! Local Tower Loads: - INTEGER(IntKi), PARAMETER :: TwHt1MLxt = 864 - INTEGER(IntKi), PARAMETER :: TwHt1MLyt = 865 - INTEGER(IntKi), PARAMETER :: TwHt1MLzt = 866 - INTEGER(IntKi), PARAMETER :: TwHt2MLxt = 867 - INTEGER(IntKi), PARAMETER :: TwHt2MLyt = 868 - INTEGER(IntKi), PARAMETER :: TwHt2MLzt = 869 - INTEGER(IntKi), PARAMETER :: TwHt3MLxt = 870 - INTEGER(IntKi), PARAMETER :: TwHt3MLyt = 871 - INTEGER(IntKi), PARAMETER :: TwHt3MLzt = 872 - INTEGER(IntKi), PARAMETER :: TwHt4MLxt = 873 - INTEGER(IntKi), PARAMETER :: TwHt4MLyt = 874 - INTEGER(IntKi), PARAMETER :: TwHt4MLzt = 875 - INTEGER(IntKi), PARAMETER :: TwHt5MLxt = 876 - INTEGER(IntKi), PARAMETER :: TwHt5MLyt = 877 - INTEGER(IntKi), PARAMETER :: TwHt5MLzt = 878 - INTEGER(IntKi), PARAMETER :: TwHt6MLxt = 879 - INTEGER(IntKi), PARAMETER :: TwHt6MLyt = 880 - INTEGER(IntKi), PARAMETER :: TwHt6MLzt = 881 - INTEGER(IntKi), PARAMETER :: TwHt7MLxt = 882 - INTEGER(IntKi), PARAMETER :: TwHt7MLyt = 883 - INTEGER(IntKi), PARAMETER :: TwHt7MLzt = 884 - INTEGER(IntKi), PARAMETER :: TwHt8MLxt = 885 - INTEGER(IntKi), PARAMETER :: TwHt8MLyt = 886 - INTEGER(IntKi), PARAMETER :: TwHt8MLzt = 887 - INTEGER(IntKi), PARAMETER :: TwHt9MLxt = 888 - INTEGER(IntKi), PARAMETER :: TwHt9MLyt = 889 - INTEGER(IntKi), PARAMETER :: TwHt9MLzt = 890 - INTEGER(IntKi), PARAMETER :: TwHt1FLxt = 891 - INTEGER(IntKi), PARAMETER :: TwHt1FLyt = 892 - INTEGER(IntKi), PARAMETER :: TwHt1FLzt = 893 - INTEGER(IntKi), PARAMETER :: TwHt2FLxt = 894 - INTEGER(IntKi), PARAMETER :: TwHt2FLyt = 895 - INTEGER(IntKi), PARAMETER :: TwHt2FLzt = 896 - INTEGER(IntKi), PARAMETER :: TwHt3FLxt = 897 - INTEGER(IntKi), PARAMETER :: TwHt3FLyt = 898 - INTEGER(IntKi), PARAMETER :: TwHt3FLzt = 899 - INTEGER(IntKi), PARAMETER :: TwHt4FLxt = 900 - INTEGER(IntKi), PARAMETER :: TwHt4FLyt = 901 - INTEGER(IntKi), PARAMETER :: TwHt4FLzt = 902 - INTEGER(IntKi), PARAMETER :: TwHt5FLxt = 903 - INTEGER(IntKi), PARAMETER :: TwHt5FLyt = 904 - INTEGER(IntKi), PARAMETER :: TwHt5FLzt = 905 - INTEGER(IntKi), PARAMETER :: TwHt6FLxt = 906 - INTEGER(IntKi), PARAMETER :: TwHt6FLyt = 907 - INTEGER(IntKi), PARAMETER :: TwHt6FLzt = 908 - INTEGER(IntKi), PARAMETER :: TwHt7FLxt = 909 - INTEGER(IntKi), PARAMETER :: TwHt7FLyt = 910 - INTEGER(IntKi), PARAMETER :: TwHt7FLzt = 911 - INTEGER(IntKi), PARAMETER :: TwHt8FLxt = 912 - INTEGER(IntKi), PARAMETER :: TwHt8FLyt = 913 - INTEGER(IntKi), PARAMETER :: TwHt8FLzt = 914 - INTEGER(IntKi), PARAMETER :: TwHt9FLxt = 915 - INTEGER(IntKi), PARAMETER :: TwHt9FLyt = 916 - INTEGER(IntKi), PARAMETER :: TwHt9FLzt = 917 + INTEGER(IntKi), PARAMETER :: TwHt1MLxt = 869 + INTEGER(IntKi), PARAMETER :: TwHt1MLyt = 870 + INTEGER(IntKi), PARAMETER :: TwHt1MLzt = 871 + INTEGER(IntKi), PARAMETER :: TwHt2MLxt = 872 + INTEGER(IntKi), PARAMETER :: TwHt2MLyt = 873 + INTEGER(IntKi), PARAMETER :: TwHt2MLzt = 874 + INTEGER(IntKi), PARAMETER :: TwHt3MLxt = 875 + INTEGER(IntKi), PARAMETER :: TwHt3MLyt = 876 + INTEGER(IntKi), PARAMETER :: TwHt3MLzt = 877 + INTEGER(IntKi), PARAMETER :: TwHt4MLxt = 878 + INTEGER(IntKi), PARAMETER :: TwHt4MLyt = 879 + INTEGER(IntKi), PARAMETER :: TwHt4MLzt = 880 + INTEGER(IntKi), PARAMETER :: TwHt5MLxt = 881 + INTEGER(IntKi), PARAMETER :: TwHt5MLyt = 882 + INTEGER(IntKi), PARAMETER :: TwHt5MLzt = 883 + INTEGER(IntKi), PARAMETER :: TwHt6MLxt = 884 + INTEGER(IntKi), PARAMETER :: TwHt6MLyt = 885 + INTEGER(IntKi), PARAMETER :: TwHt6MLzt = 886 + INTEGER(IntKi), PARAMETER :: TwHt7MLxt = 887 + INTEGER(IntKi), PARAMETER :: TwHt7MLyt = 888 + INTEGER(IntKi), PARAMETER :: TwHt7MLzt = 889 + INTEGER(IntKi), PARAMETER :: TwHt8MLxt = 890 + INTEGER(IntKi), PARAMETER :: TwHt8MLyt = 891 + INTEGER(IntKi), PARAMETER :: TwHt8MLzt = 892 + INTEGER(IntKi), PARAMETER :: TwHt9MLxt = 893 + INTEGER(IntKi), PARAMETER :: TwHt9MLyt = 894 + INTEGER(IntKi), PARAMETER :: TwHt9MLzt = 895 + INTEGER(IntKi), PARAMETER :: TwHt1FLxt = 896 + INTEGER(IntKi), PARAMETER :: TwHt1FLyt = 897 + INTEGER(IntKi), PARAMETER :: TwHt1FLzt = 898 + INTEGER(IntKi), PARAMETER :: TwHt2FLxt = 899 + INTEGER(IntKi), PARAMETER :: TwHt2FLyt = 900 + INTEGER(IntKi), PARAMETER :: TwHt2FLzt = 901 + INTEGER(IntKi), PARAMETER :: TwHt3FLxt = 902 + INTEGER(IntKi), PARAMETER :: TwHt3FLyt = 903 + INTEGER(IntKi), PARAMETER :: TwHt3FLzt = 904 + INTEGER(IntKi), PARAMETER :: TwHt4FLxt = 905 + INTEGER(IntKi), PARAMETER :: TwHt4FLyt = 906 + INTEGER(IntKi), PARAMETER :: TwHt4FLzt = 907 + INTEGER(IntKi), PARAMETER :: TwHt5FLxt = 908 + INTEGER(IntKi), PARAMETER :: TwHt5FLyt = 909 + INTEGER(IntKi), PARAMETER :: TwHt5FLzt = 910 + INTEGER(IntKi), PARAMETER :: TwHt6FLxt = 911 + INTEGER(IntKi), PARAMETER :: TwHt6FLyt = 912 + INTEGER(IntKi), PARAMETER :: TwHt6FLzt = 913 + INTEGER(IntKi), PARAMETER :: TwHt7FLxt = 914 + INTEGER(IntKi), PARAMETER :: TwHt7FLyt = 915 + INTEGER(IntKi), PARAMETER :: TwHt7FLzt = 916 + INTEGER(IntKi), PARAMETER :: TwHt8FLxt = 917 + INTEGER(IntKi), PARAMETER :: TwHt8FLyt = 918 + INTEGER(IntKi), PARAMETER :: TwHt8FLzt = 919 + INTEGER(IntKi), PARAMETER :: TwHt9FLxt = 920 + INTEGER(IntKi), PARAMETER :: TwHt9FLyt = 921 + INTEGER(IntKi), PARAMETER :: TwHt9FLzt = 922 ! Internal Degrees of Freedom: - INTEGER(IntKi), PARAMETER :: Q_B1E1 = 918 - INTEGER(IntKi), PARAMETER :: Q_B2E1 = 919 - INTEGER(IntKi), PARAMETER :: Q_B3E1 = 920 - INTEGER(IntKi), PARAMETER :: Q_B1F1 = 921 - INTEGER(IntKi), PARAMETER :: Q_B2F1 = 922 - INTEGER(IntKi), PARAMETER :: Q_B3F1 = 923 - INTEGER(IntKi), PARAMETER :: Q_B1F2 = 924 - INTEGER(IntKi), PARAMETER :: Q_B2F2 = 925 - INTEGER(IntKi), PARAMETER :: Q_B3F2 = 926 - INTEGER(IntKi), PARAMETER :: Q_Teet = 927 - INTEGER(IntKi), PARAMETER :: Q_DrTr = 928 - INTEGER(IntKi), PARAMETER :: Q_GeAz = 929 - INTEGER(IntKi), PARAMETER :: Q_RFrl = 930 - INTEGER(IntKi), PARAMETER :: Q_TFrl = 931 - INTEGER(IntKi), PARAMETER :: Q_Yaw = 932 - INTEGER(IntKi), PARAMETER :: Q_TFA1 = 933 - INTEGER(IntKi), PARAMETER :: Q_TSS1 = 934 - INTEGER(IntKi), PARAMETER :: Q_TFA2 = 935 - INTEGER(IntKi), PARAMETER :: Q_TSS2 = 936 - INTEGER(IntKi), PARAMETER :: Q_Sg = 937 - INTEGER(IntKi), PARAMETER :: Q_Sw = 938 - INTEGER(IntKi), PARAMETER :: Q_Hv = 939 - INTEGER(IntKi), PARAMETER :: Q_R = 940 - INTEGER(IntKi), PARAMETER :: Q_P = 941 - INTEGER(IntKi), PARAMETER :: Q_Y = 942 - INTEGER(IntKi), PARAMETER :: QD_B1E1 = 943 - INTEGER(IntKi), PARAMETER :: QD_B2E1 = 944 - INTEGER(IntKi), PARAMETER :: QD_B3E1 = 945 - INTEGER(IntKi), PARAMETER :: QD_B1F1 = 946 - INTEGER(IntKi), PARAMETER :: QD_B2F1 = 947 - INTEGER(IntKi), PARAMETER :: QD_B3F1 = 948 - INTEGER(IntKi), PARAMETER :: QD_B1F2 = 949 - INTEGER(IntKi), PARAMETER :: QD_B2F2 = 950 - INTEGER(IntKi), PARAMETER :: QD_B3F2 = 951 - INTEGER(IntKi), PARAMETER :: QD_Teet = 952 - INTEGER(IntKi), PARAMETER :: QD_DrTr = 953 - INTEGER(IntKi), PARAMETER :: QD_GeAz = 954 - INTEGER(IntKi), PARAMETER :: QD_RFrl = 955 - INTEGER(IntKi), PARAMETER :: QD_TFrl = 956 - INTEGER(IntKi), PARAMETER :: QD_Yaw = 957 - INTEGER(IntKi), PARAMETER :: QD_TFA1 = 958 - INTEGER(IntKi), PARAMETER :: QD_TSS1 = 959 - INTEGER(IntKi), PARAMETER :: QD_TFA2 = 960 - INTEGER(IntKi), PARAMETER :: QD_TSS2 = 961 - INTEGER(IntKi), PARAMETER :: QD_Sg = 962 - INTEGER(IntKi), PARAMETER :: QD_Sw = 963 - INTEGER(IntKi), PARAMETER :: QD_Hv = 964 - INTEGER(IntKi), PARAMETER :: QD_R = 965 - INTEGER(IntKi), PARAMETER :: QD_P = 966 - INTEGER(IntKi), PARAMETER :: QD_Y = 967 - INTEGER(IntKi), PARAMETER :: QD2_B1E1 = 968 - INTEGER(IntKi), PARAMETER :: QD2_B2E1 = 969 - INTEGER(IntKi), PARAMETER :: QD2_B3E1 = 970 - INTEGER(IntKi), PARAMETER :: QD2_B1F1 = 971 - INTEGER(IntKi), PARAMETER :: QD2_B2F1 = 972 - INTEGER(IntKi), PARAMETER :: QD2_B3F1 = 973 - INTEGER(IntKi), PARAMETER :: QD2_B1F2 = 974 - INTEGER(IntKi), PARAMETER :: QD2_B2F2 = 975 - INTEGER(IntKi), PARAMETER :: QD2_B3F2 = 976 - INTEGER(IntKi), PARAMETER :: QD2_Teet = 977 - INTEGER(IntKi), PARAMETER :: QD2_DrTr = 978 - INTEGER(IntKi), PARAMETER :: QD2_GeAz = 979 - INTEGER(IntKi), PARAMETER :: QD2_RFrl = 980 - INTEGER(IntKi), PARAMETER :: QD2_TFrl = 981 - INTEGER(IntKi), PARAMETER :: QD2_Yaw = 982 - INTEGER(IntKi), PARAMETER :: QD2_TFA1 = 983 - INTEGER(IntKi), PARAMETER :: QD2_TSS1 = 984 - INTEGER(IntKi), PARAMETER :: QD2_TFA2 = 985 - INTEGER(IntKi), PARAMETER :: QD2_TSS2 = 986 - INTEGER(IntKi), PARAMETER :: QD2_Sg = 987 - INTEGER(IntKi), PARAMETER :: QD2_Sw = 988 - INTEGER(IntKi), PARAMETER :: QD2_Hv = 989 - INTEGER(IntKi), PARAMETER :: QD2_R = 990 - INTEGER(IntKi), PARAMETER :: QD2_P = 991 - INTEGER(IntKi), PARAMETER :: QD2_Y = 992 + INTEGER(IntKi), PARAMETER :: Q_B1E1 = 923 + INTEGER(IntKi), PARAMETER :: Q_B2E1 = 924 + INTEGER(IntKi), PARAMETER :: Q_B3E1 = 925 + INTEGER(IntKi), PARAMETER :: Q_B1F1 = 926 + INTEGER(IntKi), PARAMETER :: Q_B2F1 = 927 + INTEGER(IntKi), PARAMETER :: Q_B3F1 = 928 + INTEGER(IntKi), PARAMETER :: Q_B1F2 = 929 + INTEGER(IntKi), PARAMETER :: Q_B2F2 = 930 + INTEGER(IntKi), PARAMETER :: Q_B3F2 = 931 + INTEGER(IntKi), PARAMETER :: Q_Teet = 932 + INTEGER(IntKi), PARAMETER :: Q_DrTr = 933 + INTEGER(IntKi), PARAMETER :: Q_GeAz = 934 + INTEGER(IntKi), PARAMETER :: Q_RFrl = 935 + INTEGER(IntKi), PARAMETER :: Q_TFrl = 936 + INTEGER(IntKi), PARAMETER :: Q_Yaw = 937 + INTEGER(IntKi), PARAMETER :: Q_TFA1 = 938 + INTEGER(IntKi), PARAMETER :: Q_TSS1 = 939 + INTEGER(IntKi), PARAMETER :: Q_TFA2 = 940 + INTEGER(IntKi), PARAMETER :: Q_TSS2 = 941 + INTEGER(IntKi), PARAMETER :: Q_Sg = 942 + INTEGER(IntKi), PARAMETER :: Q_Sw = 943 + INTEGER(IntKi), PARAMETER :: Q_Hv = 944 + INTEGER(IntKi), PARAMETER :: Q_R = 945 + INTEGER(IntKi), PARAMETER :: Q_P = 946 + INTEGER(IntKi), PARAMETER :: Q_Y = 947 + INTEGER(IntKi), PARAMETER :: QD_B1E1 = 948 + INTEGER(IntKi), PARAMETER :: QD_B2E1 = 949 + INTEGER(IntKi), PARAMETER :: QD_B3E1 = 950 + INTEGER(IntKi), PARAMETER :: QD_B1F1 = 951 + INTEGER(IntKi), PARAMETER :: QD_B2F1 = 952 + INTEGER(IntKi), PARAMETER :: QD_B3F1 = 953 + INTEGER(IntKi), PARAMETER :: QD_B1F2 = 954 + INTEGER(IntKi), PARAMETER :: QD_B2F2 = 955 + INTEGER(IntKi), PARAMETER :: QD_B3F2 = 956 + INTEGER(IntKi), PARAMETER :: QD_Teet = 957 + INTEGER(IntKi), PARAMETER :: QD_DrTr = 958 + INTEGER(IntKi), PARAMETER :: QD_GeAz = 959 + INTEGER(IntKi), PARAMETER :: QD_RFrl = 960 + INTEGER(IntKi), PARAMETER :: QD_TFrl = 961 + INTEGER(IntKi), PARAMETER :: QD_Yaw = 962 + INTEGER(IntKi), PARAMETER :: QD_TFA1 = 963 + INTEGER(IntKi), PARAMETER :: QD_TSS1 = 964 + INTEGER(IntKi), PARAMETER :: QD_TFA2 = 965 + INTEGER(IntKi), PARAMETER :: QD_TSS2 = 966 + INTEGER(IntKi), PARAMETER :: QD_Sg = 967 + INTEGER(IntKi), PARAMETER :: QD_Sw = 968 + INTEGER(IntKi), PARAMETER :: QD_Hv = 969 + INTEGER(IntKi), PARAMETER :: QD_R = 970 + INTEGER(IntKi), PARAMETER :: QD_P = 971 + INTEGER(IntKi), PARAMETER :: QD_Y = 972 + INTEGER(IntKi), PARAMETER :: QD2_B1E1 = 973 + INTEGER(IntKi), PARAMETER :: QD2_B2E1 = 974 + INTEGER(IntKi), PARAMETER :: QD2_B3E1 = 975 + INTEGER(IntKi), PARAMETER :: QD2_B1F1 = 976 + INTEGER(IntKi), PARAMETER :: QD2_B2F1 = 977 + INTEGER(IntKi), PARAMETER :: QD2_B3F1 = 978 + INTEGER(IntKi), PARAMETER :: QD2_B1F2 = 979 + INTEGER(IntKi), PARAMETER :: QD2_B2F2 = 980 + INTEGER(IntKi), PARAMETER :: QD2_B3F2 = 981 + INTEGER(IntKi), PARAMETER :: QD2_Teet = 982 + INTEGER(IntKi), PARAMETER :: QD2_DrTr = 983 + INTEGER(IntKi), PARAMETER :: QD2_GeAz = 984 + INTEGER(IntKi), PARAMETER :: QD2_RFrl = 985 + INTEGER(IntKi), PARAMETER :: QD2_TFrl = 986 + INTEGER(IntKi), PARAMETER :: QD2_Yaw = 987 + INTEGER(IntKi), PARAMETER :: QD2_TFA1 = 988 + INTEGER(IntKi), PARAMETER :: QD2_TSS1 = 989 + INTEGER(IntKi), PARAMETER :: QD2_TFA2 = 990 + INTEGER(IntKi), PARAMETER :: QD2_TSS2 = 991 + INTEGER(IntKi), PARAMETER :: QD2_Sg = 992 + INTEGER(IntKi), PARAMETER :: QD2_Sw = 993 + INTEGER(IntKi), PARAMETER :: QD2_Hv = 994 + INTEGER(IntKi), PARAMETER :: QD2_R = 995 + INTEGER(IntKi), PARAMETER :: QD2_P = 996 + INTEGER(IntKi), PARAMETER :: QD2_Y = 997 ! The maximum number of output channels which can be output by the code. - INTEGER(IntKi), PARAMETER :: MaxOutPts = 992 + INTEGER(IntKi), PARAMETER :: MaxOutPts = 997 -!End of code generated by Matlab script +!End of code generated by Matlab script Write_ChckOutLst ! =================================================================================================== - INTEGER, PARAMETER :: TipDxc( 3) = (/TipDxc1, TipDxc2, TipDxc3/) INTEGER, PARAMETER :: TipDyc( 3) = (/TipDyc1, TipDyc2, TipDyc3/) INTEGER, PARAMETER :: TipDzc( 3) = (/TipDzc1, TipDzc2, TipDzc3/) @@ -3505,6 +3519,47 @@ SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, BldFile, FurlFile, TwrFile RETURN END IF + !---------------------- YAW-FRICTION -------------------------------------------- + CALL ReadCom( UnIn, InputFile, 'Section Header: Yaw-Friction', ErrStat2, ErrMsg2, UnEc ) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! YawFrctMod - Yaw-friction model switch (-): + CALL ReadVar( UnIn, InputFile, InputFileData%YawFrctMod, "YawFrctMod", "Yaw-friction model switch (-)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! M_CSmax - Maximum Coulomb friction torque (N-m): + CALL ReadVar( UnIn, InputFile, InputFileData%M_CSmax, "M_CSmax", "Maximum Coulomb friction torque (N-m)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! M_CD - Dynamic friction moment at null yaw rate (N-m): + CALL ReadVar( UnIn, InputFile, InputFileData%M_CD, "M_CD", "Dynamic friction moment at null yaw rate (N-m)", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + ! sig_v - Viscous friction coefficiant (N-m s/rad): + CALL ReadVar( UnIn, InputFile, InputFileData%sig_v, "sig_v", "Viscous friction coefficient (N-m/(rad/s))", ErrStat2, ErrMsg2, UnEc) + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + IF ( ErrStat >= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF + + !---------------------- DRIVETRAIN ---------------------------------------------- CALL ReadCom( UnIn, InputFile, 'Section Header: Drivetrain', ErrStat2, ErrMsg2, UnEc ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) @@ -4533,6 +4588,14 @@ SUBROUTINE ValidatePrimaryData( InputFileData, BD4Blades, Linearize, MHK, ErrSta END IF + !Yaw-Friction User input checks + IF ( ( InputFileData%YawFrctMod /= 0_IntKi ) .AND. ( InputFileData%YawFrctMod /= 1_IntKi ) .AND. & + ( InputFileData%YawFrctMod /= 2_IntKi ) .AND. ( InputFileData%YawFrctMod /= 3_IntKi )) & + CALL SetErrStat( ErrID_Fatal, 'YawFrctMod must be 0, 1, 2, or 3',ErrStat,ErrMsg,RoutineName) + IF ( InputFileData%M_CD < 0_R8Ki ) CALL SetErrStat( ErrID_Fatal, 'M_CD must be greater than or equal to 0.',ErrStat,ErrMsg,RoutineName ) + IF ( InputFileData%M_CSmax < 0_R8Ki ) CALL SetErrStat( ErrID_Fatal, 'M_CSmax must be greater than or equal to 0.',ErrStat,ErrMsg,RoutineName ) + IF ( InputFileData%sig_v < 0_R8Ki ) CALL SetErrStat( ErrID_Fatal, 'sig_v must be greater than or equal to 0.',ErrStat,ErrMsg,RoutineName ) + !bjj: since ED doesn't actually use OutFmt at this point, I'm going to remove this check and warning message !!!! ! Check that InputFileData%OutFmt is a valid format specifier and will fit over the column headings !!!!CALL ChkRealFmtStr( InputFileData%OutFmt, 'OutFmt', FmtWidth, ErrStat2, ErrMsg2 ) diff --git a/modules/elastodyn/src/ElastoDyn_Registry.txt b/modules/elastodyn/src/ElastoDyn_Registry.txt index 935d2ccc46..c8bdd12b08 100644 --- a/modules/elastodyn/src/ElastoDyn_Registry.txt +++ b/modules/elastodyn/src/ElastoDyn_Registry.txt @@ -164,6 +164,10 @@ typedef ^ ED_InputFile ReKi TeetSStP - - - "Rotor-teeter soft-stop position" rad typedef ^ ED_InputFile ReKi TeetHStP - - - "Rotor-teeter hard-stop position" radians typedef ^ ED_InputFile ReKi TeetSSSp - - - "Rotor-teeter soft-stop linear-spring constant" N-m/rad typedef ^ ED_InputFile ReKi TeetHSSp - - - "Rotor-teeter hard-stop linear-spring constant" N-m/rad +typedef ^ ED_InputFile IntKi YawFrctMod - - - "Identifier for YawFrctMod (0 [no friction], 1 [does not use Fz at bearing], 2 [does use Fz at bearing], or 3 [user defined model]" - +typedef ^ ED_InputFile R8Ki M_CD - - - "Dynamic friction moment at null yaw rate" N-m +typedef ^ ED_InputFile R8Ki M_CSMAX - - - "Maximum Coulomb friction torque" N-m +typedef ^ ED_InputFile R8Ki sig_v - - - "Viscous friction coefficient" N-m/(rad/s) typedef ^ ED_InputFile ReKi GBoxEff - - - "Gearbox efficiency" % typedef ^ ED_InputFile ReKi GBRatio - - - "Gearbox ratio" - typedef ^ ED_InputFile ReKi DTTorSpr - - - "Drivetrain torsional spring" N-m/rad @@ -492,6 +496,7 @@ typedef ^ ED_RtHndSide ReKi TFrlMom - - - "The total tail-furl spring and damper typedef ^ ED_RtHndSide ReKi RFrlMom - - - "The total rotor-furl spring and damper moment" typedef ^ ED_RtHndSide ReKi GBoxEffFac - - - "The factor used to apply the gearbox efficiency effects to the equation associated with the generator DOF" typedef ^ ED_RtHndSide ReKi rSAerCen {:}{:}{:} - - "aerodynamic pitching moment arm (i.e., the position vector from point S on the blade to the aerodynamic center of the element)" +typedef ^ ED_RtHndSide ReKi YawFriMom - - - "Yaw Friction Moment" kN-m # ..... States .................................................................................................................... # Define continuous (differentiable) states here: @@ -512,6 +517,10 @@ typedef ^ OtherStateType ReKi HSSBrTrq - - - "HSSBrTrq from update states; a hac typedef ^ OtherStateType ReKi HSSBrTrqC - - - "Commanded HSS brake torque (adjusted for sign)" N-m typedef ^ OtherStateType IntKi SgnPrvLSTQ - - - "The sign of the low-speed shaft torque from the previous call to RtHS(). This is calculated at the end of RtHS(). NOTE: The low-speed shaft torque is assumed to be positive at the beginning of the run!" - typedef ^ OtherStateType IntKi SgnLSTQ {ED_NMX} - - "history of sign of LSTQ" +typedef ^ OtherStateType ReKi Mfhat - - - "Final Yaw Friction Torque" N-m +typedef ^ OtherStateType ReKi YawFriMfp - - - "Yaw Friction Torque to bring yaw system to a stop at current time step" N-m +typedef ^ OtherStateType R8Ki OmegaTn - - - "Yaw rate at t_n used to calculate friction torque and yaw rate at t_n+1" rad/s +typedef ^ OtherStateType R8Ki OmegaDotTn - - - "Yaw acceleration at t_n used to calculate friction torque and yaw rate at t_n+1" rad/s^2 # ..... Misc Vars ................................................................................................................ typedef ^ MiscVarType ED_CoordSys CoordSys - - - "Coordinate systems in the FAST framework" - @@ -524,6 +533,9 @@ typedef ^ MiscVarType IntKi AugMat_pivot {:} - - "Pivot column for AugMat in LAP typedef ^ MiscVarType ReKi OgnlGeAzRo {:} - - "Original DOF_GeAz row in AugMat" - typedef ^ MiscVarType R8Ki QD2T {:} - - "Solution (acceleration) vector; the first time derivative of QDT" typedef ^ MiscVarType Logical IgnoreMod - - - "whether to ignore the modulo in ED outputs (necessary for linearization perturbations)" - +typedef ^ MiscVarType ReKi OgnlYawRow {:} - - "Original DOF_Yaw row in AugMat" - +typedef ^ MiscVarType ReKi FrcONcRt - - - "Fz acting on yaw bearing including inertial contributions" N +typedef ^ MiscVarType ReKi YawFriMz - - - "External loading on yaw bearing not including inertial contributions" N-m # ..... Parameters ................................................................................................................ # Define parameters here: @@ -740,6 +752,13 @@ typedef ^ ParameterType ReKi PtfmCMxt - - - "Downwind distance from the ground l typedef ^ ParameterType ReKi PtfmCMyt - - - "Lateral distance from the ground level [onshore], MSL [offshore wind or floating MHK], or seabed [fixed MHK] to the platform CM" meters typedef ^ ParameterType LOGICAL BD4Blades - - - "flag to determine if BeamDyn is computing blade loads (true) or ElastoDyn is (false)" - typedef ^ ParameterType LOGICAL UseAD14 - - - "flag to determine if AeroDyn14 is being used. Will remove this later when we've replaced AD14." - +typedef ^ ParameterType IntKi YawFrctMod - - - "Identifier for YawFrctMod (0 [no friction], 1 [does not use Fz at bearing], or 2 [does use Fz at bearing]" - +typedef ^ ParameterType R8Ki M_CD - - - "Dynamic friction moment at null yaw rate" N-m +typedef ^ ParameterType R8Ki M_CSMAX - - - "Maximum Coulomb friction torque" N-m +typedef ^ ParameterType R8Ki sig_v - - - "Viscous friction coefficient" N-m/(rad/s) +#typedef ^ ParameterType R8Ki thr_omg - - - "Yaw rate stiction threshold" rad/s +#typedef ^ ParameterType R8Ki thr_omgdot - - - "Yaw acceleration stiction threshold" rad/s^2 + # .... ED_AllBlNds option ........................................................................................................ typedef ^ ParameterType IntKi BldNd_NumOuts - - - "Number of requested output channels per blade node (ED_AllBldNdOuts)" - typedef ^ ParameterType IntKi BldNd_TotNumOuts - - - "Total number of requested output channels of blade node information (BldNd_NumOuts * BldNd_BlOutNd * BldNd_BladesOut -- ED_AllBldNdOuts)" - diff --git a/modules/elastodyn/src/ElastoDyn_Types.f90 b/modules/elastodyn/src/ElastoDyn_Types.f90 index c80a1c72ca..99c18e3276 100644 --- a/modules/elastodyn/src/ElastoDyn_Types.f90 +++ b/modules/elastodyn/src/ElastoDyn_Types.f90 @@ -186,6 +186,10 @@ MODULE ElastoDyn_Types REAL(ReKi) :: TeetHStP = 0.0_ReKi !< Rotor-teeter hard-stop position [radians] REAL(ReKi) :: TeetSSSp = 0.0_ReKi !< Rotor-teeter soft-stop linear-spring constant [N-m/rad] REAL(ReKi) :: TeetHSSp = 0.0_ReKi !< Rotor-teeter hard-stop linear-spring constant [N-m/rad] + INTEGER(IntKi) :: YawFrctMod = 0_IntKi !< Identifier for YawFrctMod (0 [no friction], 1 [does not use Fz at bearing], 2 [does use Fz at bearing], or 3 [user defined model] [-] + REAL(R8Ki) :: M_CD = 0.0_R8Ki !< Dynamic friction moment at null yaw rate [N-m] + REAL(R8Ki) :: M_CSMAX = 0.0_R8Ki !< Maximum Coulomb friction torque [N-m] + REAL(R8Ki) :: sig_v = 0.0_R8Ki !< Viscous friction coefficient [N-m/(rad/s)] REAL(ReKi) :: GBoxEff = 0.0_ReKi !< Gearbox efficiency [%] REAL(ReKi) :: GBRatio = 0.0_ReKi !< Gearbox ratio [-] REAL(ReKi) :: DTTorSpr = 0.0_ReKi !< Drivetrain torsional spring [N-m/rad] @@ -492,6 +496,7 @@ MODULE ElastoDyn_Types REAL(ReKi) :: RFrlMom = 0.0_ReKi !< The total rotor-furl spring and damper moment [-] REAL(ReKi) :: GBoxEffFac = 0.0_ReKi !< The factor used to apply the gearbox efficiency effects to the equation associated with the generator DOF [-] REAL(ReKi) , DIMENSION(:,:,:), ALLOCATABLE :: rSAerCen !< aerodynamic pitching moment arm (i.e., the position vector from point S on the blade to the aerodynamic center of the element) [-] + REAL(ReKi) :: YawFriMom = 0.0_ReKi !< Yaw Friction Moment [kN-m] END TYPE ED_RtHndSide ! ======================= ! ========= ED_ContinuousStateType ======= @@ -519,6 +524,10 @@ MODULE ElastoDyn_Types REAL(ReKi) :: HSSBrTrqC = 0.0_ReKi !< Commanded HSS brake torque (adjusted for sign) [N-m] INTEGER(IntKi) :: SgnPrvLSTQ = 0_IntKi !< The sign of the low-speed shaft torque from the previous call to RtHS(). This is calculated at the end of RtHS(). NOTE: The low-speed shaft torque is assumed to be positive at the beginning of the run! [-] INTEGER(IntKi) , DIMENSION(1:ED_NMX) :: SgnLSTQ = 0_IntKi !< history of sign of LSTQ [-] + REAL(ReKi) :: Mfhat = 0.0_ReKi !< Final Yaw Friction Torque [N-m] + REAL(ReKi) :: YawFriMfp = 0.0_ReKi !< Yaw Friction Torque to bring yaw system to a stop at current time step [N-m] + REAL(R8Ki) :: OmegaTn = 0.0_R8Ki !< Yaw rate at t_n used to calculate friction torque and yaw rate at t_n+1 [rad/s] + REAL(R8Ki) :: OmegaDotTn = 0.0_R8Ki !< Yaw acceleration at t_n used to calculate friction torque and yaw rate at t_n+1 [rad/s^2] END TYPE ED_OtherStateType ! ======================= ! ========= ED_MiscVarType ======= @@ -533,6 +542,9 @@ MODULE ElastoDyn_Types REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OgnlGeAzRo !< Original DOF_GeAz row in AugMat [-] REAL(R8Ki) , DIMENSION(:), ALLOCATABLE :: QD2T !< Solution (acceleration) vector; the first time derivative of QDT [-] LOGICAL :: IgnoreMod = .false. !< whether to ignore the modulo in ED outputs (necessary for linearization perturbations) [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: OgnlYawRow !< Original DOF_Yaw row in AugMat [-] + REAL(ReKi) :: FrcONcRt = 0.0_ReKi !< Fz acting on yaw bearing including inertial contributions [N] + REAL(ReKi) :: YawFriMz = 0.0_ReKi !< External loading on yaw bearing not including inertial contributions [N-m] END TYPE ED_MiscVarType ! ======================= ! ========= ED_ParameterType ======= @@ -747,6 +759,10 @@ MODULE ElastoDyn_Types REAL(ReKi) :: PtfmCMyt = 0.0_ReKi !< Lateral distance from the ground level [onshore], MSL [offshore wind or floating MHK], or seabed [fixed MHK] to the platform CM [meters] LOGICAL :: BD4Blades = .false. !< flag to determine if BeamDyn is computing blade loads (true) or ElastoDyn is (false) [-] LOGICAL :: UseAD14 = .false. !< flag to determine if AeroDyn14 is being used. Will remove this later when we've replaced AD14. [-] + INTEGER(IntKi) :: YawFrctMod = 0_IntKi !< Identifier for YawFrctMod (0 [no friction], 1 [does not use Fz at bearing], or 2 [does use Fz at bearing] [-] + REAL(R8Ki) :: M_CD = 0.0_R8Ki !< Dynamic friction moment at null yaw rate [N-m] + REAL(R8Ki) :: M_CSMAX = 0.0_R8Ki !< Maximum Coulomb friction torque [N-m] + REAL(R8Ki) :: sig_v = 0.0_R8Ki !< Viscous friction coefficient [N-m/(rad/s)] INTEGER(IntKi) :: BldNd_NumOuts = 0_IntKi !< Number of requested output channels per blade node (ED_AllBldNdOuts) [-] INTEGER(IntKi) :: BldNd_TotNumOuts = 0_IntKi !< Total number of requested output channels of blade node information (BldNd_NumOuts * BldNd_BlOutNd * BldNd_BladesOut -- ED_AllBldNdOuts) [-] TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: BldNd_OutParam !< Names and units (and other characteristics) of all requested output parameters [-] @@ -1656,6 +1672,10 @@ subroutine ED_CopyInputFile(SrcInputFileData, DstInputFileData, CtrlCode, ErrSta DstInputFileData%TeetHStP = SrcInputFileData%TeetHStP DstInputFileData%TeetSSSp = SrcInputFileData%TeetSSSp DstInputFileData%TeetHSSp = SrcInputFileData%TeetHSSp + DstInputFileData%YawFrctMod = SrcInputFileData%YawFrctMod + DstInputFileData%M_CD = SrcInputFileData%M_CD + DstInputFileData%M_CSMAX = SrcInputFileData%M_CSMAX + DstInputFileData%sig_v = SrcInputFileData%sig_v DstInputFileData%GBoxEff = SrcInputFileData%GBoxEff DstInputFileData%GBRatio = SrcInputFileData%GBRatio DstInputFileData%DTTorSpr = SrcInputFileData%DTTorSpr @@ -2018,6 +2038,10 @@ subroutine ED_PackInputFile(RF, Indata) call RegPack(RF, InData%TeetHStP) call RegPack(RF, InData%TeetSSSp) call RegPack(RF, InData%TeetHSSp) + call RegPack(RF, InData%YawFrctMod) + call RegPack(RF, InData%M_CD) + call RegPack(RF, InData%M_CSMAX) + call RegPack(RF, InData%sig_v) call RegPack(RF, InData%GBoxEff) call RegPack(RF, InData%GBRatio) call RegPack(RF, InData%DTTorSpr) @@ -2211,6 +2235,10 @@ subroutine ED_UnPackInputFile(RF, OutData) call RegUnpack(RF, OutData%TeetHStP); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TeetSSSp); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TeetHSSp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%YawFrctMod); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%M_CD); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%M_CSMAX); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%sig_v); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%GBoxEff); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%GBRatio); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%DTTorSpr); if (RegCheckErr(RF, RoutineName)) return @@ -3965,6 +3993,7 @@ subroutine ED_CopyRtHndSide(SrcRtHndSideData, DstRtHndSideData, CtrlCode, ErrSta end if DstRtHndSideData%rSAerCen = SrcRtHndSideData%rSAerCen end if + DstRtHndSideData%YawFriMom = SrcRtHndSideData%YawFriMom end subroutine subroutine ED_DestroyRtHndSide(RtHndSideData, ErrStat, ErrMsg) @@ -4331,6 +4360,7 @@ subroutine ED_PackRtHndSide(RF, Indata) call RegPack(RF, InData%RFrlMom) call RegPack(RF, InData%GBoxEffFac) call RegPackAlloc(RF, InData%rSAerCen) + call RegPack(RF, InData%YawFriMom) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -4485,6 +4515,7 @@ subroutine ED_UnPackRtHndSide(RF, OutData) call RegUnpack(RF, OutData%RFrlMom); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%GBoxEffFac); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%rSAerCen); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%YawFriMom); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine ED_CopyContState(SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg) @@ -4674,6 +4705,10 @@ subroutine ED_CopyOtherState(SrcOtherStateData, DstOtherStateData, CtrlCode, Err DstOtherStateData%HSSBrTrqC = SrcOtherStateData%HSSBrTrqC DstOtherStateData%SgnPrvLSTQ = SrcOtherStateData%SgnPrvLSTQ DstOtherStateData%SgnLSTQ = SrcOtherStateData%SgnLSTQ + DstOtherStateData%Mfhat = SrcOtherStateData%Mfhat + DstOtherStateData%YawFriMfp = SrcOtherStateData%YawFriMfp + DstOtherStateData%OmegaTn = SrcOtherStateData%OmegaTn + DstOtherStateData%OmegaDotTn = SrcOtherStateData%OmegaDotTn end subroutine subroutine ED_DestroyOtherState(OtherStateData, ErrStat, ErrMsg) @@ -4716,6 +4751,10 @@ subroutine ED_PackOtherState(RF, Indata) call RegPack(RF, InData%HSSBrTrqC) call RegPack(RF, InData%SgnPrvLSTQ) call RegPack(RF, InData%SgnLSTQ) + call RegPack(RF, InData%Mfhat) + call RegPack(RF, InData%YawFriMfp) + call RegPack(RF, InData%OmegaTn) + call RegPack(RF, InData%OmegaDotTn) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -4739,6 +4778,10 @@ subroutine ED_UnPackOtherState(RF, OutData) call RegUnpack(RF, OutData%HSSBrTrqC); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%SgnPrvLSTQ); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%SgnLSTQ); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%Mfhat); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%YawFriMfp); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%OmegaTn); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%OmegaDotTn); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine ED_CopyMisc(SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg) @@ -4844,6 +4887,20 @@ subroutine ED_CopyMisc(SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg) DstMiscData%QD2T = SrcMiscData%QD2T end if DstMiscData%IgnoreMod = SrcMiscData%IgnoreMod + if (allocated(SrcMiscData%OgnlYawRow)) then + LB(1:1) = lbound(SrcMiscData%OgnlYawRow, kind=B8Ki) + UB(1:1) = ubound(SrcMiscData%OgnlYawRow, kind=B8Ki) + if (.not. allocated(DstMiscData%OgnlYawRow)) then + allocate(DstMiscData%OgnlYawRow(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%OgnlYawRow.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMiscData%OgnlYawRow = SrcMiscData%OgnlYawRow + end if + DstMiscData%FrcONcRt = SrcMiscData%FrcONcRt + DstMiscData%YawFriMz = SrcMiscData%YawFriMz end subroutine subroutine ED_DestroyMisc(MiscData, ErrStat, ErrMsg) @@ -4880,6 +4937,9 @@ subroutine ED_DestroyMisc(MiscData, ErrStat, ErrMsg) if (allocated(MiscData%QD2T)) then deallocate(MiscData%QD2T) end if + if (allocated(MiscData%OgnlYawRow)) then + deallocate(MiscData%OgnlYawRow) + end if end subroutine subroutine ED_PackMisc(RF, Indata) @@ -4897,6 +4957,9 @@ subroutine ED_PackMisc(RF, Indata) call RegPackAlloc(RF, InData%OgnlGeAzRo) call RegPackAlloc(RF, InData%QD2T) call RegPack(RF, InData%IgnoreMod) + call RegPackAlloc(RF, InData%OgnlYawRow) + call RegPack(RF, InData%FrcONcRt) + call RegPack(RF, InData%YawFriMz) if (RegCheckErr(RF, RoutineName)) return end subroutine @@ -4918,6 +4981,9 @@ subroutine ED_UnPackMisc(RF, OutData) call RegUnpackAlloc(RF, OutData%OgnlGeAzRo); if (RegCheckErr(RF, RoutineName)) return call RegUnpackAlloc(RF, OutData%QD2T); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%IgnoreMod); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%OgnlYawRow); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%FrcONcRt); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%YawFriMz); if (RegCheckErr(RF, RoutineName)) return end subroutine subroutine ED_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) @@ -5743,6 +5809,10 @@ subroutine ED_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) DstParamData%PtfmCMyt = SrcParamData%PtfmCMyt DstParamData%BD4Blades = SrcParamData%BD4Blades DstParamData%UseAD14 = SrcParamData%UseAD14 + DstParamData%YawFrctMod = SrcParamData%YawFrctMod + DstParamData%M_CD = SrcParamData%M_CD + DstParamData%M_CSMAX = SrcParamData%M_CSMAX + DstParamData%sig_v = SrcParamData%sig_v DstParamData%BldNd_NumOuts = SrcParamData%BldNd_NumOuts DstParamData%BldNd_TotNumOuts = SrcParamData%BldNd_TotNumOuts if (allocated(SrcParamData%BldNd_OutParam)) then @@ -6233,6 +6303,10 @@ subroutine ED_PackParam(RF, Indata) call RegPack(RF, InData%PtfmCMyt) call RegPack(RF, InData%BD4Blades) call RegPack(RF, InData%UseAD14) + call RegPack(RF, InData%YawFrctMod) + call RegPack(RF, InData%M_CD) + call RegPack(RF, InData%M_CSMAX) + call RegPack(RF, InData%sig_v) call RegPack(RF, InData%BldNd_NumOuts) call RegPack(RF, InData%BldNd_TotNumOuts) call RegPack(RF, allocated(InData%BldNd_OutParam)) @@ -6489,6 +6563,10 @@ subroutine ED_UnPackParam(RF, OutData) call RegUnpack(RF, OutData%PtfmCMyt); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%BD4Blades); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%UseAD14); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%YawFrctMod); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%M_CD); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%M_CSMAX); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%sig_v); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%BldNd_NumOuts); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%BldNd_TotNumOuts); if (RegCheckErr(RF, RoutineName)) return if (allocated(OutData%BldNd_OutParam)) deallocate(OutData%BldNd_OutParam) diff --git a/modules/lindyn/CMakeLists.txt b/modules/lindyn/CMakeLists.txt new file mode 100644 index 0000000000..4e010d16e5 --- /dev/null +++ b/modules/lindyn/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright 2016 National Renewable Energy Laboratory +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +if (GENERATE_TYPES) + generate_f90_types(src/LinDyn_Registry.txt ${CMAKE_CURRENT_LIST_DIR}/src/LinDyn_Types.f90) +endif() + +add_library(lindynlib + src/LinDyn.f90 + src/LinDyn_Types.f90 +) +target_link_libraries(lindynlib nwtclibs) + +install(TARGETS lindynlib + EXPORT "${CMAKE_PROJECT_NAME}Libraries" + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/modules/lindyn/README.md b/modules/lindyn/README.md new file mode 100644 index 0000000000..564ae516eb --- /dev/null +++ b/modules/lindyn/README.md @@ -0,0 +1,4 @@ +# LinDyn Module + +## Overview +A module for linear dynamics (m, c, k, f) in OpenFAST diff --git a/modules/lindyn/src/LinDyn.f90 b/modules/lindyn/src/LinDyn.f90 new file mode 100644 index 0000000000..9ae64598f4 --- /dev/null +++ b/modules/lindyn/src/LinDyn.f90 @@ -0,0 +1,938 @@ +!********************************************************************************************************************************** +!> LinDyn, module for a second order linear dynamical system with mass, stiffness and damping matrix +!! +!! The state is q = [x; xdot], of shape nq = 2*nx +!! The input is F_ext of shape nx +!! The equation of motion is: +!! +!! qdot = [xdot ] = [ 0 I ] [ x ] + [ 0 ] F_ext +!! [xddot] [-M^{-1} K -M^{-1} C ] [ xdot] + [M^{-1}] +!! +!! .................................................................................................................................. +!! ## Licensing +!! Copyright (C) 2012-2013, 2015-2016 National Renewable Energy Laboratory +!! +!! This file is part of LinDyn. +!! +!! Licensed under the Apache License, Version 2.0 (the "License"); +!! you may not use this file except in compliance with the License. +!! You may obtain a copy of the License at +!! +!! http://www.apache.org/licenses/LICENSE-2.0 +!! +!! Unless required by applicable law or agreed to in writing, software +!! distributed under the License is distributed on an "AS IS" BASIS, +!! WITHout WARRANTIES OR CONDITIONS OF ANY KinD, either express or implied. +!! See the License for the specific language governing permissions and +!! limitations under the License. +!********************************************************************************************************************************** +module LinDyn + + use LinDyn_Types + use NWTC_Library + USE NWTC_LAPACK +! + implicit none + + type(ProgDesc), parameter :: LD_Ver = ProgDesc( 'LinDyn', '', '' ) + + private + + public :: LD_Init ! Initialization routine + public :: LD_InitInputData ! Set default values and allocations for init + public :: LD_End ! Ending routine (includes clean up) + public :: LD_UpdateStates ! Loose coupling routine for solving for constraint states, integrating continuous states, and updating discrete states + public :: LD_CalcOutput ! Routine for computing outputs + public :: LD_CalcContStateDeriv ! Tight coupling routine for computing derivatives of continuous states + public :: LD_JacobianPInput ! Jacobians of (y, x, xd, z) with respect to the inputs (u) + public :: LD_JacobianPContState ! Jacobians of (y, x, xd, z) with respect to the continuous (x) + public :: LD_GetOP ! Routine to get the operating-point values for linearization (from data structures to arrays) +! +contains + +subroutine LD_Init(InitInp, u, p, x, xd, z, OtherState, y, m, InitOut, errStat, errMsg) + type(LD_InitInputType), intent(in ) :: InitInp !< Input data for initialization routine + type(LD_InputType), intent(out) :: u !< An initial guess for the input; input mesh must be defined + type(LD_ParameterType), intent(out) :: p !< Parameters + type(LD_ContinuousStateType), intent(out) :: x !< Initial continuous states + type(LD_DiscreteStateType), intent(out) :: xd !< Initial discrete states + type(LD_ConstraintStateType), intent(out) :: z !< Initial guess of the constraint states + type(LD_OtherStateType), intent(out) :: OtherState !< Initial other states (logical, etc) + type(LD_OutputType), intent(out) :: y !< Initial system outputs (outputs are not calculated; + type(LD_MiscVarType), intent(out) :: m !< Misc variables for optimization (not copied in glue code) + type(LD_InitOutputType), intent(out) :: InitOut !< Output for initialization routine + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + ! Misc Init + errStat = ErrID_None + errMsg = "" + call NWTC_Init( ) ! Initialize the NWTC Subroutine Library + call DispNVD( LD_Ver ) ! Display the module information + + ! --- Setting Params from InitInp + p%nx = size(InitInp%MM,1) + p%nq = 2*p%nx + call AllocAry(p%MM , p%nx, p%nx, 'MM', errStat2, errMsg2); if(Failed()) return + call AllocAry(p%CC , p%nx, p%nx, 'CC', errStat2, errMsg2); if(Failed()) return + call AllocAry(p%KK , p%nx, p%nx, 'KK', errStat2, errMsg2); if(Failed()) return + call AllocAry(p%activeDOFs, p%nx , 'activeDOFs', errStat2, errMsg2); if(Failed()) return + p%dt = InitInp%dt + p%IntMethod = InitInp%IntMethod + p%MM = InitInp%MM + p%CC = InitInp%CC + p%KK = InitInp%KK + p%activeDOFs = InitInp%activeDOFs + ! Prescribed motion + if (len_trim(InitInp%PrescribedMotionFile)>0) then + if( count(p%activeDOFs)/=0) then + errStat2 = errID_Fatal + errMsg2 = 'Currently, prescribed motion is only allowed if all degrees of freedom are turned off' + if(Failed()) return + endif + call WrScr(' Using prescribed motion.') + call ReadDelimFile(InitInp%PrescribedMotionFile, (p%nx*3+1), p%PrescribedValues, errStat2, errMsg2); if(Failed()) return + else + if (allocated(p%PrescribedValues)) deallocate(p%PrescribedValues) + endif + call StateMatrices(p%MM, p%CC, p%KK, p%AA, p%BB, errStat2, errMsg2); if(Failed()) return + + ! --- Misc + call allocAry(m%qPrescribed, 3*p%nx, 'qPrescribed', errStat2, errMsg2); if(Failed()) return + m%qPrescribed = 0.0_ReKi ! NOTE: will be updated by LD_SetInitialConditions + + ! --- Allocate States + call AllocAry( x%q , p%nq, 'DOFs', errStat, errMsg); if(Failed()) return + call LD_SetInitialConditions(x, InitInp%x0, InitInp%xd0, p, OtherState, m, errStat, errMsg); if(Failed()) return + if ( ( p%IntMethod .eq. 2) .OR. ( p%IntMethod .eq. 3)) then !Multi-step methods + allocate( OtherState%xdot(4), STAT=errStat2); errMsg2='Error allocating OtherState%xdot' + if(Failed()) return + endif + + ! --- Guess inputs + call AllocAry(u%Fext, p%nx, 'Fext', errStat2, errMsg2); if(Failed()) return + u%Fext=0.0_ReKi + + ! --- Outputs & Write Outputs + call Init_Outputs(p, m, y, InitInp, InitOut, errStat, errMsg); if(Failed()) return + InitOut%Ver = LD_Ver + + ! --- Linearization + if (InitInp%Linearize) then + call Init_Lin(p, InitOut, errStat, errMsg); if(Failed()) return + endif +! +! ! --- Summary file +! if (InputFileData%SumPrint) then +! TODO use yaml +! print*,'' +! print*,'M',p%MM(1,:) +! print*,'M',p%MM(2,:) +! print*,'M',p%MM(3,:) +! print*,'' +! print*,'C',p%CC(1,:) +! print*,'C',p%CC(2,:) +! print*,'C',p%CC(3,:) +! print*,'' +! print*,'K',p%KK(1,:) +! print*,'K',p%KK(2,:) +! print*,'K',p%KK(3,:) +! print*,'' +! +! print*,'' +! print*,'A',p%AA(1,:) +! print*,'A',p%AA(2,:) +! print*,'A',p%AA(3,:) +! print*,'A',p%AA(4,:) +! print*,'A',p%AA(5,:) +! print*,'A',p%AA(6,:) +! print*,'' +! print*,'B',p%BB(1,:) +! print*,'B',p%BB(2,:) +! print*,'B',p%BB(3,:) +! print*,'B',p%BB(4,:) +! print*,'B',p%BB(5,:) +! print*,'B',p%BB(6,:) +! endif +! +contains + logical function Failed() + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'LD_Init' ) + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + subroutine CleanUp() + end subroutine CleanUp +end subroutine LD_Init +!---------------------------------------------------------------------------------------------------------------------------------- +subroutine LD_SetInitialConditions(x, x0, xd0, p, OtherState, m, errStat, errMsg) + type(LD_ContinuousStateType), intent(inout) :: x !< Initial continuous states + real(ReKi), intent(in) :: x0(:) !< Values of the positions at t=0 + real(ReKi), intent(in) :: xd0(:) !< Velocity values at t=0 + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_OtherStateType), intent(inout) :: OtherState !< Other states + type(LD_MiscVarType), intent(inout) :: m !< Misc variables for optimization (not copied in glue code) + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + integer :: nx + nx = int(size(x%q)/2) + errStat = ErrID_Fatal + if (size(x0)/=size(xd0)) then + errMsg ='Shape of x0 and xd0 should match when setting intial conditions'; return + endif + if (size(x0)/=nx) then + errMsg ='Shape of x0 should match nx when setting intial conditions'; return + endif + errMsg = '' + errStat = ErrID_None + + if (allocated(p%PrescribedValues)) then + call interpTimeValue(p%PrescribedValues, 0.0_DbKi, OtherState%iMotionInterpLast, m%qPrescribed(:)) + ! TODO the code below will need to be updated if a subset of the DOFs are active + x%q(1:p%nq) = m%qPrescribed(1:p%nq) + else + x%q( 1:nx) = x0 + x%q(nx+1:2*nx) = xd0 + endif +end subroutine LD_SetInitialConditions +!---------------------------------------------------------------------------------------------------------------------------------- +!> Allocate init input data for module based on number of degrees of freedom +subroutine LD_InitInputData(nx, InitInp, errStat, errMsg) + integer(IntKi), intent(in ) :: nx !< Number of degrees of freedom + type(LD_InitInputType), intent(out) :: InitInp !< Input data for initialization routine + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + integer(IntKi) :: iDOF + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + ! Initialize errStat + errStat = ErrID_None ! no error has occurred + errMsg = "" + call AllocAry(InitInp%MM , nx, nx, 'MM' , errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInp%CC , nx, nx, 'CC' , errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInp%KK , nx, nx, 'KK' , errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInp%x0 , nx , 'x0' , errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInp%xd0 , nx , 'xd0', errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInp%activeDOFs, nx , 'activeDOFs', errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInp%DOFsNames , nx , 'DOFsNames' , errStat2, errMsg2); if(Failed()) return + call AllocAry(InitInp%DOFsUnits , nx , 'DOFsUnits' , errStat2, errMsg2); if(Failed()) return + InitInp%MM = 0.0_ReKi + InitInp%CC = 0.0_ReKi + InitInp%KK = 0.0_ReKi + InitInp%x0 = 0.0_ReKi + InitInp%xd0 = 0.0_ReKi + InitInp%activeDOFs = .True. + ! Default DOFs Names and Units + do iDOF=1,nx + InitInp%DOFsNames(iDOF)='x'//trim(num2lstr(iDOF)) + InitInp%DOFsUnits(iDOF)='-' + enddo + +contains + logical function Failed() + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'LD_Init' ) + Failed = ErrStat >= AbortErrLev + end function Failed +end subroutine LD_InitInputData +!---------------------------------------------------------------------------------------------------------------------------------- +!> Compute A and B state matrices for a linear mechanical system +!! NOTE: Generic function (no derived types), keep it that way +!! A = [ 0 I ] B = [0 ] +!! [-M^{-1}K -M^{-1}C ] = [-M^{-1}] +subroutine StateMatrices(MM, CC, KK, AA, BB, errStat, errMsg) + real(ReKi), intent(in ) :: MM(:,:) + real(ReKi), intent(in ) :: CC(:,:) + real(ReKi), intent(in ) :: KK(:,:) + real(ReKi), allocatable, intent(out) :: AA(:,:) + real(ReKi), allocatable, intent(out) :: BB(:,:) + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + integer :: nx, nq, i + real(ReKi), dimension(:,:), allocatable :: MLU ! LU factorization of M matrix + real(ReKi), dimension(:,:), allocatable :: MinvX ! Tmp array to store either: M^{-1} C, M^{-1} K , or M^{-1} + real(ReKi), dimension(:) , allocatable :: WORK ! LAPACK variable + integer, allocatable :: IPIV(:) ! LAPACK variable + integer :: LWORK ! LAPACK variable + ! Initialize errStat + errStat = ErrID_None + errMsg = "" + + ! --- Init A and B matrix + nx = size(MM,1) + nq = 2*nx + call AllocAry(AA, nq, nq, 'AA', errStat2, errMsg2); if(Failed()) return + call AllocAry(BB, nq, nx, 'BB', errStat2, errMsg2); if(Failed()) return + AA(:,:) = 0.0_ReKi + BB(:,:) = 0.0_ReKi + do i=1,nx ; AA(i,i+nx)=1; enddo ! Identity matrix for upper right block + + ! --- Compute misc inverse of M and put in A and B matrices + call AllocAry(IPIV , nx , 'IPIV' , errStat2, errMsg2); if(Failed()) return + call AllocAry(MinvX , nx, nx, 'MinvX', errStat2, errMsg2); if(Failed()) return + call AllocAry(MLU , nx, nx, 'MLU' , errStat2, errMsg2); if(Failed()) return + + ! LU Factorization of M + MLU = MM ! temp copy + call LAPACK_getrf(nx, nx, MLU, IPIV, errStat2, errMsg2); if(Failed()) return + + ! M^-1 C + MinvX = CC + call LAPACK_getrs('n', nx, MLU, IPIV, MinvX, errStat2, errMsg2); if(Failed()) return + AA(nx+1:nq,nx+1:nq) = -MinvX + + ! M^-1 K + MinvX = KK + call LAPACK_getrs('n', nx, MLU, IPIV, MinvX, errStat2, errMsg2); if(Failed()) return + AA(nx+1:nq, 1:nx) = -MinvX + + ! Inverse of M + MinvX = MLU + LWORK=nx*nx ! Somehow LWORK = -1 does not work + allocate(WORK(LWORk)) + call LAPACK_getri(nx, MinvX, IPIV, WORK, LWORK, errStat2, errMsg2); if(Failed()) return + BB(nx+1:nq, : ) = -MinvX + +contains + logical function Failed() + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'StateMatrices' ) + Failed = ErrStat >= AbortErrLev + if (Failed) call CleanUp() + end function Failed + subroutine CleanUp() + if (allocated(MLU)) deallocate(MLU) + if (allocated(IPIV)) deallocate(IPIV) + if (allocated(WORK )) deallocate(WORK) + if (allocated(MinvX)) deallocate(MinvX) + end subroutine CleanUp +end subroutine StateMatrices +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine is called at the end of the simulation. +subroutine LD_End( u, p, x, xd, z, OtherState, y, m, errStat, errMsg ) + type(LD_InputType), intent(inout) :: u !< System inputs + type(LD_ParameterType), intent(inout) :: p !< Parameters + type(LD_ContinuousStateType), intent(inout) :: x !< Continuous states + type(LD_DiscreteStateType), intent(inout) :: xd !< Discrete states + type(LD_ConstraintStateType), intent(inout) :: z !< Constraint states + type(LD_OtherStateType), intent(inout) :: OtherState !< Other states + type(LD_OutputType), intent(inout) :: y !< System outputs + type(LD_MiscVarType), intent(inout) :: m !< Misc variables for optimization (not copied in glue code) + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + ! Initialize errStat + errStat = ErrID_None ! no error has occurred + errMsg = "" + call LD_DestroyInput (u ,errStat,errMsg) + call LD_DestroyParam (p ,errStat,errMsg) + call LD_DestroyContState (x ,errStat,errMsg) + call LD_DestroyDiscState (xd ,errStat,errMsg) + call LD_DestroyConstrState(z ,errStat,errMsg) + call LD_DestroyOtherState (OtherState,errStat,errMsg) + call LD_DestroyOutput (y ,errStat,errMsg) + call LD_DestroyMisc (m ,errStat,errMsg) +end subroutine LD_End +!---------------------------------------------------------------------------------------------------------------------------------- +!> Fourth-order Adams-Bashforth Method (RK4) for numerically integration (see ElastoDyn.f9) +subroutine LD_AB4( t, n, u, utimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< time step number + type(LD_InputType), intent(inout) :: u(:) !< Inputs at t + real(DbKi), intent(in ) :: utimes(:) !< times of input + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(inout) :: x !< Continuous states at t on input at t + dt on output + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at t (possibly a guess) + type(LD_OtherStateType), intent(inout) :: OtherState !< Other states at t on input at t + dt on output + type(LD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + ! local variables + type(LD_ContinuousStateType) :: xdot ! Continuous state derivs at t + type(LD_InputType) :: u_interp + ! Initialize errStat + errStat = ErrID_None + errMsg = "" + + ! need xdot at t + call LD_CopyInput(u(1), u_interp, MESH_NEWCOPY, errStat, errMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + call LD_Input_ExtrapInterp(u, utimes, u_interp, t, errStat, errMsg) + call LD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, errStat, errMsg ) ! initializes xdot + call LD_DestroyInput( u_interp, errStat, errMsg) ! we don't need this local copy anymore + if (n .le. 2) then + OtherState%n = n + call LD_CopyContState(xdot, OtherState%xdot(3-n), MESH_UPDATECOPY, errStat, errMsg ) + call LD_RK4(t, n, u, utimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + else + if (OtherState%n .lt. n) then + OtherState%n = n + call LD_CopyContState(OtherState%xdot(3), OtherState%xdot(4), MESH_UPDATECOPY, errStat, errMsg ) + call LD_CopyContState(OtherState%xdot(2), OtherState%xdot(3), MESH_UPDATECOPY, errStat, errMsg ) + call LD_CopyContState(OtherState%xdot(1), OtherState%xdot(2), MESH_UPDATECOPY, errStat, errMsg ) + elseif (OtherState%n .gt. n) then + errStat = ErrID_Fatal + errMsg = ' Backing up in time is not supported with a multistep method ' + return + endif + call LD_CopyContState( xdot, OtherState%xdot ( 1 ), MESH_UPDATECOPY, errStat, errMsg ) + !OtherState%xdot ( 1 ) = xdot ! make sure this is most up to date + x%q = x%q + (p%dt / 24._ReKi) * (55._ReKi*OtherState%xdot(1)%q - 59._ReKi*OtherState%xdot(2)%q + 37._ReKi*OtherState%xdot(3)%q - 9._ReKi * OtherState%xdot(4)%q) + endif + call LD_DestroyContState(xdot, errStat, errMsg) + call LD_DestroyInput(u_interp, errStat, errMsg) +end subroutine LD_AB4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Fourth-order Adams-Bashforth-Moulton Method (RK4) for numerically integrating (see ElastoDyn.f90) +subroutine LD_ABM4( t, n, u, utimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< time step number + type(LD_InputType), intent(inout) :: u(:) !< Inputs at t + real(DbKi), intent(in ) :: utimes(:) !< times of input + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(inout) :: x !< Continuous states at t on input at t + dt on output ! TODO TODO TODO in + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at t (possibly a guess) + type(LD_OtherStateType), intent(inout) :: OtherState !< Other states at t on input at t + dt on output + type(LD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + ! local variables + type(LD_InputType) :: u_interp ! Continuous states at t + type(LD_ContinuousStateType) :: x_pred ! Continuous states at t + type(LD_ContinuousStateType) :: xdot_pred ! Continuous states at t + ! Initialize errStat + errStat = ErrID_None + errMsg = "" + call LD_CopyContState(x, x_pred, MESH_NEWCOPY, errStat, errMsg) !initialize x_pred + call LD_AB4( t, n, u, utimes, p, x_pred, xd, z, OtherState, m, errStat, errMsg ) + if (n .gt. 2) then + call LD_CopyInput( u(1), u_interp, MESH_NEWCOPY, errStat, errMsg) ! make copy so that arrays/meshes get initialized/allocated for ExtrapInterp + call LD_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, errStat, errMsg) + call LD_CalcContStateDeriv(t + p%dt, u_interp, p, x_pred, xd, z, OtherState, m, xdot_pred, errStat, errMsg ) ! initializes xdot_pred + call LD_DestroyInput( u_interp, errStat, errMsg) ! local copy no longer needed + + x%q = x%q + (p%dt / 24.) * ( 9. * xdot_pred%q + 19. * OtherState%xdot(1)%q - 5. * OtherState%xdot(2)%q + 1. * OtherState%xdot(3)%q ) + call LD_DestroyContState( xdot_pred, errStat, errMsg) ! local copy no longer needed + else + x%q = x_pred%q + endif + call LD_DestroyContState( x_pred, errStat, errMsg) ! local copy no longer needed +end subroutine LD_ABM4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Fourth-order Runge-Kutta Method (RK4) for numerically integration (see ElastoDyn.f90) +subroutine LD_RK4( t, n, u, utimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< time step number + type(LD_InputType), intent(inout) :: u(:) !< Inputs at t + real(DbKi), intent(in ) :: utimes(:) !< times of input + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(inout) :: x !< Continuous states at t on input at t + dt on output + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at t (possibly a guess) + type(LD_OtherStateType), intent(inout) :: OtherState !< Other states at t on input at t + dt on output + type(LD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + ! local variables + type(LD_ContinuousStateType) :: xdot ! time derivatives of continuous states + type(LD_ContinuousStateType) :: k1 ! RK4 constant; see above + type(LD_ContinuousStateType) :: k2 ! RK4 constant; see above + type(LD_ContinuousStateType) :: k3 ! RK4 constant; see above + type(LD_ContinuousStateType) :: k4 ! RK4 constant; see above + type(LD_ContinuousStateType) :: x_tmp ! Holds temporary modification to x + type(LD_InputType) :: u_interp ! interpolated value of inputs + ! Initialize errStat + errStat = ErrID_None + errMsg = "" + + ! Initialize interim vars + call LD_CopyContState( x, k1, MESH_NEWCOPY, errStat, errMsg ) + call LD_CopyContState( x, k2, MESH_NEWCOPY, errStat, errMsg ) + call LD_CopyContState( x, k3, MESH_NEWCOPY, errStat, errMsg ) + call LD_CopyContState( x, k4, MESH_NEWCOPY, errStat, errMsg ) + call LD_CopyContState( x, x_tmp, MESH_NEWCOPY, errStat, errMsg ) + + ! interpolate u to find u_interp = u(t) + call LD_CopyInput(u(1), u_interp, MESH_NEWCOPY, errStat, errMsg ) ! we need to allocate input arrays/meshes before calling ExtrapInterp... + call LD_Input_ExtrapInterp( u, utimes, u_interp, t, errStat, errMsg ) + + ! find xdot at t + call LD_CalcContStateDeriv( t, u_interp, p, x, xd, z, OtherState, m, xdot, errStat, errMsg ) !initializes xdot + + k1%q = p%dt * xdot%q + x_tmp%q = x%q + 0.5_ReKi * k1%q + + ! interpolate u to find u_interp = u(t + dt/2) + call LD_Input_ExtrapInterp(u, utimes, u_interp, t+0.5_ReKi*p%dt, errStat, errMsg) + + ! find xdot at t + dt/2 + call LD_CalcContStateDeriv( t + 0.5_ReKi*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, errStat, errMsg ) + + k2%q = p%dt * xdot%q + x_tmp%q = x%q + 0.5_ReKi * k2%q + + ! find xdot at t + dt/2 + call LD_CalcContStateDeriv( t + 0.5_ReKi*p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, errStat, errMsg ) + + k3%q = p%dt * xdot%q + x_tmp%q = x%q + k3%q + + ! interpolate u to find u_interp = u(t + dt) + call LD_Input_ExtrapInterp(u, utimes, u_interp, t + p%dt, errStat, errMsg) + + ! find xdot at t + dt + call LD_CalcContStateDeriv( t + p%dt, u_interp, p, x_tmp, xd, z, OtherState, m, xdot, errStat, errMsg ) + k4%q = p%dt * xdot%q + x%q = x%q + ( k1%q + 2._ReKi * k2%q + 2._ReKi * k3%q + k4%q ) / 6._ReKi + call CleanUp() +contains + subroutine CleanUp() + integer(IntKi) :: errStat3 ! The error identifier (errStat) + character(1024) :: errMsg3 ! The error message (errMsg) + call LD_DestroyContState( xdot, errStat3, errMsg3 ) + call LD_DestroyContState( k1, errStat3, errMsg3 ) + call LD_DestroyContState( k2, errStat3, errMsg3 ) + call LD_DestroyContState( k3, errStat3, errMsg3 ) + call LD_DestroyContState( k4, errStat3, errMsg3 ) + call LD_DestroyContState( x_tmp, errStat3, errMsg3 ) + call LD_DestroyInput( u_interp, errStat3, errMsg3 ) + end subroutine CleanUp +end subroutine LD_RK4 +!---------------------------------------------------------------------------------------------------------------------------------- +!> Loose coupling routine for solving states at t+dt +subroutine LD_UpdateStates( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + integer(IntKi), intent(in ) :: n !< Current step of the simulation: t = n*dt + type(LD_InputType), intent(inout) :: Inputs(:) !< Inputs at InputTimes (output from this routine only + real(DbKi), intent(in ) :: InputTimes(:) !< Times in seconds associated with Inputs + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(inout) :: x !< Input: Continuous states at t; Output: at t+dt + type(LD_DiscreteStateType), intent(inout) :: xd !< Input: Discrete states at t; Output: at t+dt + type(LD_ConstraintStateType), intent(inout) :: z !< Input: Constraint states at t; Output: at t+dt + type(LD_OtherStateType), intent(inout) :: OtherState !< Other states: Other states at t;Output: at t+dt + type(LD_MiscVarType), intent(inout) :: m !< Misc variables for optimization (not copied in glue code) + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + ! Initialize variables + errStat = ErrID_None ! no error has occurred + errMsg = "" + if (allocated(p%PrescribedValues)) then + call interpTimeValue(p%PrescribedValues, t+p%dt, OtherState%iMotionInterpLast, m%qPrescribed(:)) + x%q(1:p%nq) = m%qPrescribed(1:p%nq) + endif + if ( p%nq == 0) return + if (p%IntMethod .eq. 1) then + call LD_RK4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + elseif (p%IntMethod .eq. 2) then + call LD_AB4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + elseif (p%IntMethod .eq. 3) then + call LD_ABM4( t, n, Inputs, InputTimes, p, x, xd, z, OtherState, m, errStat, errMsg ) + else + call SeterrStat(ErrID_Fatal,'Invalid time integration method:'//Num2LStr(p%IntMethod),errStat,errMsg,'LD_UpdateState') + end if +end subroutine LD_UpdateStates +!---------------------------------------------------------------------------------------------------------------------------------- +!> This is a routine for computing outputs, used in both loose and tight coupling. +subroutine LD_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(LD_InputType), intent(in ) :: u !< Inputs at t + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(in ) :: x !< Continuous states at t + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at t + type(LD_OtherStateType), intent(in ) :: OtherState !< Other states at t + type(LD_MiscVarType), intent(inout) :: m !< Misc variables for optimization (not copied in glue code) + type(LD_OutputType), intent(inout) :: y !< Outputs computed at t (Input only so that mesh con- + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + type(LD_ContinuousStateType) :: dxdt !< + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + errStat = ErrID_None ! no error has occurred + errMsg = "" + + ! --- Compute accelerations + if (allocated(p%PrescribedValues)) then + y%xdd(1:p%nx) = m%qPrescribed(p%nq+1:p%nq+p%nx) + else + call LD_CalcContStateDeriv(t, u, p, x, xd, z, OtherState, m, dxdt, errStat2, errMsg2) + y%xdd(1:p%nx) = dxdt%q(p%nx+1:p%nq) + endif + + !--- Computing outputs: y = Cx + Du (optional) + + ! --- Write Outputs + y%WriteOutput(1:2*p%nx) = x%q(1:p%nq) ! Positions and velocities + y%WriteOutput(2*p%nx+1:3*p%nx) = y%xdd(1:p%nx) ! Accelerations + y%WriteOutput(3*p%nx+1:4*p%nx) = u%Fext(1:p%nx) ! Forces + +contains + logical function Failed() + call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'LD_CalcOutput' ) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine LD_CalcOutput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Tight coupling routine for computing derivatives of continuous states. +subroutine LD_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, errStat, errMsg ) + real(DbKi), intent(in ) :: t !< Current simulation time in seconds + type(LD_InputType), intent(in ) :: u !< Inputs at t + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(in ) :: x !< Continuous states at t + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at t + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at t + type(LD_OtherStateType), intent(in ) :: OtherState !< Other states at t + type(LD_MiscVarType), intent(inout) :: m !< Misc variables for optimization (not copied in glue code) + type(LD_ContinuousStateType), intent(out) :: dxdt !< Continuous state derivatives at t + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + ! Local variables + integer(IntKi) :: iDOF + integer(IntKi) :: errStat2 ! Status of error message + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + ! Initialize variables + errStat = ErrID_None ! no error has occurred + errMsg = "" + ! Allocation of output dxdt (since intent(out)) + call AllocAry(dxdt%q, p%nq, 'dxdt%q', errStat2, errMsg2); if(Failed()) return + if ( p%nq == 0 ) return + + ! --- Computation of dq + ! >>> MATMUL IMPLEMENTATION + dxdt%q = matmul(p%AA,x%q) + matmul(p%BB,u%Fext) + ! >>> BLAS IMPLEMENTATION + ! COPY( N , X , inCX, Y , inCY) + !call LAPACK_COPY(p%nCB, x%qmdot , 1 , dxdt%qm , 1 ) ! qmdot=qmdot + !! GEMV(TRS, M , N , alpha , A , LDA , X ,inCX, Beta , Y , IncY) + !call LAPACK_GEMV('n', p%nq, p%nq , 1.0_ReKi, p%AA, p%nq, x%q , 1 , 1.0_ReKi, dxdt%qmdot, 1 ) ! - K22 x2 + !call LAPACK_GEMV('n', p%nq, p%nx , 1.0_ReKi, p%BB, p%nq, u%Fext, 1 , 1.0_ReKi, dxdt%qmdot, 1 ) ! - M21 \ddot{x1} + ! --- Desactivating Constant DOFs + do iDOF = 1,p%nx + if (.not. p%activeDOFs(iDOF)) then + dxdt%q(iDOF ) = 0.0_ReKi + dxdt%q(iDOF+p%nx) = 0.0_ReKi + endif + enddo + +contains + logical function Failed() + call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'LD_CalcContStateDeriv' ) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine LD_CalcContStateDeriv +!---------------------------------------------------------------------------------------------------------------------------------- +!> Setup outputs +subroutine Init_Outputs(p, m, y, InitInp, InitOut, errStat, errMsg) + ! character(ChanLen), intent(in) :: OutList(:) !< list of user-requested outputs + type(LD_ParameterType), intent(inout) :: p !< module parameters + type(LD_MiscVarType), intent(inout) :: m !< module misc + type(LD_OutputType), intent(inout) :: y !< module outputs + type(LD_InitInputType), intent(in ) :: InitInp !< module init inputs + type(LD_InitOutputType),intent(inout) :: InitOut !< module init outputs + integer(intki), intent(out) :: errStat !< error status code + character(*), intent(out) :: errMsg !< error message, if an error occurred + integer :: errStat2 ! temporary (local) error status + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + integer :: i, iOut + errStat = ErrID_None + errMsg = "" + + ! --- Regular outputs + call AllocAry(y%xdd, p%nx, 'qd', errStat2, errMsg2); if(Failed()) return + y%xdd = 0.0_ReKi + + ! --- Write Outputs + p%NumOuts = (p%nx) * (1 + 1 + 1 + 1) ! Pos, Vel, Acc, Force + + !call AllocAry(m%AllOuts, p%NumOuts, "LinDyn AllOut", errStat,errMsg ); if(Failed()) return; m%AllOuts(:) = 0.0_ReKi + call AllocAry(y%WriteOutput, p%NumOuts,'WriteOutput', errStat,errMsg); if(Failed()) return + call AllocAry(InitOut%WriteOutputHdr,p%NumOuts,'WriteOutputHdr',errStat,errMsg); if(Failed()) return + call AllocAry(InitOut%WriteOutputUnt,p%NumOuts,'WriteOutputUnt',errStat,errMsg); if(Failed()) return + y%WriteOutput(1:p%NumOuts) = 0.0 + + ! Sanity checks + if (.not. allocated(InitInp%DOFsNames)) then + errStat2 = errID_Fatal; errMsg2='DOFs Names not allocated'; if(Failed()) return + else + if(size(InitInp%DOFsNames)/=p%nx) then + errStat2 = errID_Fatal; errMsg2='Shape of DOFs Names incorrect'; if(Failed()) return + endif + if (.not.allocated(InitInp%DOFsUnits)) then + errStat2 = errID_Fatal; errMsg2='DOFs Units should be allocated if Names are provided'; if(Failed()) return + endif + if(size(InitInp%DOFsUnits)/=p%nx) then + errStat2 = errID_Fatal; errMsg2='Shape of DOFs Units incorrect'; if(Failed()) return + endif + endif + + iOut = 0 ! Cumulative counter + call SetWriteOutputsForDOFs('' ) ! Positions + call SetWriteOutputsForDOFs('d' ) ! Velocities + call SetWriteOutputsForDOFs('dd') ! Accelerations + call SetWriteOutputsForDOFs('f' ) ! Forces + + ! If using OutParam instead + !InitOut%WriteOutputHdr(1:p%NumOuts) = p%OutParam(1:p%NumOuts)%Name + !InitOut%WriteOutputUnt(1:p%NumOuts) = p%OutParam(1:p%NumOuts)%Units + ! Debug output to screen + !do i = 1,p%NumOuts + ! print*,i, InitOut%WriteOutputHdr(i), InitOut%WriteOutputUnt(i) + !enddo + +contains + subroutine SetWriteOutputsForDOFs(sPrefix) + character(len=*) :: sPrefix + do i = 1, p%nx + iOut = iOut+1 + InitOut%WriteOutputHdr(iOut) = trim(InitInp%prefix)//trim(sPrefix)//trim(InitInp%DOFsNames(i)) + ! Units + if (sPrefix == '') InitOut%WriteOutputUnt(iOut) ='('//trim(InitInp%DOFsUnits(i))//')' + if (sPrefix == 'd') InitOut%WriteOutputUnt(iOut) ='('//trim(InitInp%DOFsUnits(i))//'/s)' + if (sPrefix == 'dd') InitOut%WriteOutputUnt(iOut) ='('//trim(InitInp%DOFsUnits(i))//'/s^2)' + if (sPrefix == 'f') then + if (InitInp%DOFsUnits(i)=='m') then; InitOut%WriteOutputUnt(iOut) ='(N)' ; + elseif (InitInp%DOFsUnits(i)=='rad') then; InitOut%WriteOutputUnt(iOut) ='(Nm)' ; + else; InitOut%WriteOutputUnt(iOut) ='(-)' + endif + endif + enddo + endsubroutine + + logical function Failed() + call SetErrStat( errStat2, errMsg2, errStat, errMsg, 'Init_Outputs' ) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine Init_Outputs +!---------------------------------------------------------------------------------------------------------------------------------- +!> Setup Linearization data +subroutine Init_Lin(p, InitOut, errStat, errMsg) + type(LD_ParameterType), intent(in ) :: p !< module parameters + type(LD_InitOutputType),intent(inout) :: InitOut !< module init outputs + integer(intki), intent(out) :: errStat !< error status code + character(*), intent(out) :: errMsg !< error message, if an error occurred + integer :: errStat2 ! temporary (local) error status + character(1024) :: errMsg2 ! Error message if ErrStat /= ErrID_None + integer :: i, nu + errStat = ErrID_None + errMsg = "" + nu = p%nx + +! LinNames_y {:} - - "Names of the outputs used in linearization" - +! LinNames_x {:} - - "Names of the continuous states used in linearization" - +! LinNames_u {:} - - "Names of the inputs used in linearization" - +! RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - +! RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - +! RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +! IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +! DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - + !Appropriate Jacobian row/column names and rotating-frame flags here: + call AllocAry(InitOut%LinNames_y , p%NumOuts , 'LinNames_y', errStat, errMsg); if(Failed()) return + call AllocAry(InitOut%RotFrame_y , p%NumOuts , 'RotFrame_y', errStat, errMsg); if(Failed()) return + call AllocAry(InitOut%LinNames_x , p%nq , 'LinNames_x', errStat, errMsg); if(Failed()) return + call AllocAry(InitOut%RotFrame_x , p%nq , 'RotFrame_x', errStat, errMsg); if(Failed()) return + call AllocAry(InitOut%DerivOrder_x, p%nq , 'DerivOrd_x', errStat, errMsg); if(Failed()) return + call AllocAry(InitOut%LinNames_u , nu , 'LinNames_u', errStat, errMsg); if(Failed()) return + call AllocAry(InitOut%RotFrame_u , nu , 'RotFrame_u', errStat, errMsg); if(Failed()) return + call AllocAry(InitOut%IsLoad_u , nu , 'IsLoad_u' , errStat, errMsg); if(Failed()) return + InitOut%DerivOrder_x(:)=2 + ! LinNames_y + do i=1, p%NumOuts + InitOut%LinNames_y(i) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) + print*,'y',i, trim(InitOut%LinNames_y(i)) + enddo + ! LinNames_u + do i=1, p%nx + InitOut%LinNames_u(i) = trim(InitOut%WriteOutputHdr(3*p%nx+ i))//', '//trim(InitOut%WriteOutputUnt(3*p%nx+i)) + print*,'u',i, trim(InitOut%LinNames_u(i)) + enddo + ! LinNames_x + do I=1,p%nq; + InitOut%LinNames_x(I) = trim(InitOut%WriteOutputHdr(i))//', '//trim(InitOut%WriteOutputUnt(i)) + print*,'x',i, trim(InitOut%LinNames_x(i)) + enddo + InitOut%RotFrame_x = .false. + InitOut%RotFrame_y = .false. + InitOut%RotFrame_u = .false. + InitOut%IsLoad_u = .true. + ! +contains + logical function Failed() + if (errStat >= AbortErrLev) errMsg = 'LD_JacobianLin:'//trim(errMsg) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine Init_Lin + +!---------------------------------------------------------------------------------------------------------------------------------- +!> Jacobians with respect to inputs (u) +subroutine LD_JacobianPInput( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg, dYdu, dXdu, dXddu, dZdu) + real(DbKi), intent(in ) :: t !< Time in seconds at operating point + type(LD_InputType), intent(in ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(in ) :: x !< Continuous states at operating point + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at operating point + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at operating point + type(LD_OtherStateType), intent(in ) :: OtherState !< Other states at operating point + type(LD_OutputType), intent(in ) :: y !< Output (change to inout if a mesh copy is required); + type(LD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent( out) :: errStat !< Error status of the operation + character(*), intent( out) :: errMsg !< Error message if errStat /= ErrID_None + real(R8Ki), allocatable, optional, intent(inout) :: dYdu(:,:) !< Jacobians of output functions (Y) with respect to (u) + real(R8Ki), allocatable, optional, intent(inout) :: dXdu(:,:) !< Jacobians of continuous state functions (X) with respect to (u) + real(R8Ki), allocatable, optional, intent(inout) :: dXddu(:,:) !< Jacobians of discrete state functions (Xd) with respect to (u) + real(R8Ki), allocatable, optional, intent(inout) :: dZdu(:,:) !< Jacobians of constraint state functions (Z) with respect to (u) + integer(IntKi) :: i, nu ! Loop index + ! Initialize errStat + errStat = ErrID_None + errMsg = '' + nu = p%nx + if (present(dYdu)) then + if (.not. allocated(dYdu)) then + call AllocAry(dYdu, p%NumOuts, nu, 'dYdu', errStat, errMsg); if(Failed()) return + dYdu(:,:) = 0.0_ReKi + end if + !dYdu(1 : p%nx, :) = 0.0_ReKi ! Positions + dYdu( p%nx+1 : 3*p%nx, :) = p%BB ! Velocities and accelerations + do i=1, p%nx ; dYdu(3*p%nx+i, i) = 1.0_ReKi; enddo ! Forces (which are inputs) + end if + if (present(dXdu)) then + if (.not. allocated(dXdu)) then + call AllocAry(dXdu, p%nq, nu, 'dXdu', errStat, errMsg); if(Failed()) return + dXdu(:,:) = 0.0_ReKi + end if + dXdu = p%BB + end if + if (present(dXddu)) then + end if + if (present(dZdu)) then + end if +contains + logical function Failed() + if (errStat >= AbortErrLev) errMsg = 'LD_JacobianPInput:'//trim(errMsg) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine LD_JacobianPInput +!---------------------------------------------------------------------------------------------------------------------------------- +!> Jacobians with respect to continuous states (x) +subroutine LD_JacobianPContState( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg, dYdx, dXdx, dXddx, dZdx ) + real(DbKi), intent(in ) :: t !< Time in seconds at operating point + type(LD_InputType), intent(in ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(in ) :: x !< Continuous states at operating point + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at operating point + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at operating point + type(LD_OtherStateType), intent(in ) :: OtherState !< Other states at operating point + type(LD_OutputType), intent(in ) :: y !< Output (change to inout if a mesh copy is required); + type(LD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + real(R8Ki), allocatable, optional, intent(inout) :: dYdx(:,:) !< Jacobians of output functions (Y) with respect to (x) + real(R8Ki), allocatable, optional, intent(inout) :: dXdx(:,:) !< Jacobians of continuous state functions (X) with respect to (x) + real(R8Ki), allocatable, optional, intent(inout) :: dXddx(:,:) !< Jacobians of discrete state functions (Xd) with respect to (x) + real(R8Ki), allocatable, optional, intent(inout) :: dZdx(:,:) !< Jacobians of constraint state functions (Z) with respect to (x) + integer(IntKi) :: i ! Loop index + ! Initialize errStat + errStat = ErrID_None + errMsg = '' + if (present(dYdx)) then + ! allocate and set dYdx + if (.not. allocated(dYdx)) then + call AllocAry(dYdx, p%NumOuts, p%nq, 'dYdx', errStat, errMsg); if(Failed()) return + dYdx(:,:) = 0.0_ReKi + end if + do i=1,p%nx; dYdx(i,i) = 1.0_ReKi; enddo ! Position + dYdx(p%nx+1:3*p%nx,: ) = p%AA ! Velocity and acceleration + !dYdx(3*p%nx+1:,:) = 0 ! Forces + end if + if (present(dXdx)) then + ! allocate and set dXdx + if (.not. allocated(dXdx)) then + call AllocAry(dXdx, p%nq, p%nq, 'dXdx', errStat, errMsg); if(Failed()) return + dXdx(:,:) = 0.0_ReKi + end if + dXdx = p%AA + end if + if (present(dXddx)) then + end if + if (present(dZdx)) then + end if +contains + logical function Failed() + if (errStat >= AbortErrLev) errMsg = 'LD_JacobianPContState:'//trim(errMsg) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine LD_JacobianPContState +!---------------------------------------------------------------------------------------------------------------------------------- +!> Routine to pack the data structures representing the operating points into arrays for linearization. +subroutine LD_GetOP( t, u, p, x, xd, z, OtherState, y, m, errStat, errMsg, u_op, y_op, x_op, dx_op, xd_op, z_op ) + real(DbKi), intent(in ) :: t !< Time in seconds at operating point + type(LD_InputType), intent(in ) :: u !< Inputs at operating point (may change to inout if a mesh copy is required) + type(LD_ParameterType), intent(in ) :: p !< Parameters + type(LD_ContinuousStateType), intent(in ) :: x !< Continuous states at operating point + type(LD_DiscreteStateType), intent(in ) :: xd !< Discrete states at operating point + type(LD_ConstraintStateType), intent(in ) :: z !< Constraint states at operating point + type(LD_OtherStateType), intent(in ) :: OtherState !< Other states at operating point + type(LD_OutputType), intent(in ) :: y !< Output at operating point + type(LD_MiscVarType), intent(inout) :: m !< Misc/optimization variables + integer(IntKi), intent(out) :: errStat !< Error status of the operation + character(*), intent(out) :: errMsg !< Error message if errStat /= ErrID_None + real(ReKi), allocatable, optional, intent(inout) :: u_op(:) !< values of linearized inputs + real(ReKi), allocatable, optional, intent(inout) :: y_op(:) !< values of linearized outputs + real(ReKi), allocatable, optional, intent(inout) :: x_op(:) !< values of linearized continuous states + real(ReKi), allocatable, optional, intent(inout) :: dx_op(:) !< values of first time derivatives of linearized continuous states + real(ReKi), allocatable, optional, intent(inout) :: xd_op(:) !< values of linearized discrete states + real(ReKi), allocatable, optional, intent(inout) :: z_op(:) !< values of linearized constraint states + integer(IntKi) :: i, nu + type(LD_ContinuousStateType) :: dx !< derivative of continuous states at operating point + ! Initialize errStat + errStat = ErrID_None + errMsg = '' + nu = p%nx + + if ( present( u_op ) ) then + if (.not. allocated(u_op)) then + call AllocAry(u_op, nu, 'u_op', errStat, errMsg); if(Failed())return + endif + u_op(:) = u%Fext + end if + + if ( present( y_op ) ) then + if (.not. allocated(y_op)) then + call AllocAry(y_op, p%NumOuts, 'y_op', errStat, errMsg); if(Failed())return + endif + ! Update the output mesh + do i=1,p%NumOuts + y_op(i) = y%WriteOutput(i) + end do + end if + + if ( present( x_op ) ) then + if (.not. allocated(x_op)) then + call AllocAry(x_op, p%nq, 'x_op', errStat, errMsg); if (Failed())return + endif + x_op = x%q + end if + + if ( present( dx_op ) ) then + if (.not. allocated(dx_op)) then + call AllocAry(dx_op, p%nq, 'dx_op', errStat, errMsg); if (Failed())return + endif + call LD_CalcContStateDeriv(t, u, p, x, xd, z, OtherState, m, dx, errStat, errMsg); if(Failed()) return + dx_op = dx%q + end if + + if ( present( xd_op ) ) then + end if + + if ( present( z_op ) ) then + end if + +contains + logical function Failed() + if (errStat >= AbortErrLev) errMsg = 'LD_GetOP:'//trim(errMsg) + Failed = errStat >= AbortErrLev + end function Failed +end subroutine LD_GetOP + +end module LinDyn +!********************************************************************************************************************************** diff --git a/modules/lindyn/src/LinDyn_Registry.txt b/modules/lindyn/src/LinDyn_Registry.txt new file mode 100644 index 0000000000..6140a54fab --- /dev/null +++ b/modules/lindyn/src/LinDyn_Registry.txt @@ -0,0 +1,82 @@ +################################################################################################################################### +# Registry for Linear Dynamics Module +################################################################################################################################### +include Registry_NWTC_Library.txt + +#param ElasticSection/ES - INTEGER ES_Baseline - 1 - "UAMod = 1 [Baseline model (Original)]" - + +# ..... Initialization data ....................................................................................................... +# Initialization inputs +typedef LinDyn/LD InitInputType DbKi dt - - - "time step" s +typedef ^ ^ IntKi IntMethod - - - "Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4])" - +typedef ^ ^ ReKi MM {:}{:} - - "Mass matrix" - +typedef ^ ^ ReKi CC {:}{:} - - "Damping matrix" - +typedef ^ ^ ReKi KK {:}{:} - - "Stiffness matrix" - +typedef ^ ^ ReKi x0 {:} 0 - "Degrees of freedom initial conditions - shape nx" - +typedef ^ ^ ReKi xd0 {:} 0 - "Velocities initial conditions - shape nx" - +typedef ^ ^ logical activeDOFs {:} .true. - "Degrees of freedom that are active - shape nx" - +typedef ^ ^ character(8) prefix - "" - "Prefix for degrees of freedom write outputs" - +typedef ^ ^ character(8) DOFsNames {:} "" - "Names of degrees of freedom for write outputs" - +typedef ^ ^ character(8) DOFsUnits {:} "" - "Units of degrees of freedom for write outputs" - +typedef ^ ^ logical Linearize - .false. - "Flag that tells this module if the glue code wants to linearize." - +typedef ^ ^ character(2048) PrescribedMotionFile - "" - "Input file for prescribed motion" - + +# Initialization outputs +typedef LinDyn/LD InitOutputType ProgDesc Ver - - - "This module's name, version, and date" - +typedef ^ InitOutputType character(ChanLen) WriteOutputHdr {:} - - "The is the list of all output channel header strings (includes all sub-module channels)" - +typedef ^ ^ character(ChanLen) WriteOutputUnt {:} - - "The is the list of all output channel unit strings (includes all sub-module channels)" - +typedef ^ ^ character(LinChanLen) LinNames_y {:} - - "Names of the outputs used in linearization" - +typedef ^ ^ character(LinChanLen) LinNames_x {:} - - "Names of the continuous states used in linearization" - +typedef ^ ^ character(LinChanLen) LinNames_u {:} - - "Names of the inputs used in linearization" - +typedef ^ ^ logical RotFrame_y {:} - - "Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame" - +typedef ^ ^ logical RotFrame_x {:} - - "Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame" - +typedef ^ ^ logical RotFrame_u {:} - - "Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame" - +typedef ^ ^ logical IsLoad_u {:} - - "Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix)" - +typedef ^ ^ IntKi DerivOrder_x {:} - - "Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization" - + +# ..... States .................................................................................................................... +# Continuous states +typedef ^ ContinuousStateType ReKi q {:} - - "Continuous states q =(x,xdot)" "-" + +# Discrete (non-differentiable) states: +typedef ^ DiscreteStateType SiKi Dummy - - - "" - + +# Constraint states: +typedef ^ ConstraintStateType SiKi Dummy - - - "" - + +# Other states: +typedef ^ OtherStateType LD_ContinuousStateType xdot {:} - - "Previous state derivs for m-step time integrator" +typedef ^ ^ IntKi n - - - "Tracks time step for which OtherState was updated last" +typedef ^ ^ IntKi iMotionInterpLast - 1 - "Last index used to interpolate the presribed motion time series" - + +# ..... Misc/Optimization variables................................................................................................. +typedef ^ MiscVarType Logical Dummy - - - "" - +typedef ^ ^ ReKi qPrescribed {:} - - "Prescribed motion/velocity/accelerations for all degrees of freedom at a given time" - + + +# ..... Parameters ................................................................................................................ +typedef ^ ParameterType DbKi dt - - - "time step" s +typedef ^ ^ IntKi IntMethod - - - "Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4])" - +typedef ^ ^ IntKi nx - - - "Number of degrees of freedom (size of M)" - +typedef ^ ^ IntKi nq - - - "nq=2*nx" - +typedef ^ ^ ReKi MM {:}{:} - - "Mass Matrix - shape (nx x nx)" - +typedef ^ ^ ReKi CC {:}{:} - - "Damping Matrix - shape (nx x nx)" - +typedef ^ ^ ReKi KK {:}{:} - - "Stiffness Matrix - shape (nx x nx)" - +typedef ^ ^ ReKi Minv {:}{:} - - "Inverse of Mass matrix" - +typedef ^ ^ Logical activeDOFs {:} - - "Degrees of freedom that are active" - +typedef ^ ^ ReKi AA {:}{:} - - "State matrix A - shape (nq x nq) " - +typedef ^ ^ ReKi BB {:}{:} - - "State matrix B - shape (nq x nx) " - +typedef ^ ^ IntKi NumOuts - - - "Number of values in WriteOutput" - +typedef ^ ^ OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - +typedef ^ ^ IntKi OutParamLinIndx {:}{:} - - "Index into WriteOutput for linearization analysis" - +typedef ^ ^ ReKi PrescribedValues {:}{:} - - "Prescribed motion for all degrees of freedom" - + + + +# ..... Inputs .................................................................................................................... +typedef ^ InputType ReKi Fext : - - "External loads - shape nx" + +# ..... Outputs ................................................................................................................... +typedef ^ OutputType ReKi xdd {:} - "Time derivative of continuous states" - +typedef ^ ^ ReKi WriteOutput {:} - - "outputs to be written to a file" - + diff --git a/modules/lindyn/src/LinDyn_Types.f90 b/modules/lindyn/src/LinDyn_Types.f90 new file mode 100644 index 0000000000..ebaaa657a2 --- /dev/null +++ b/modules/lindyn/src/LinDyn_Types.f90 @@ -0,0 +1,1559 @@ +!STARTOFREGISTRYGENERATEDFILE 'LinDyn_Types.f90' +! +! WARNING This file is generated automatically by the FAST registry. +! Do not edit. Your changes to this file will be lost. +! +! FAST Registry +!********************************************************************************************************************************* +! LinDyn_Types +!................................................................................................................................. +! This file is part of LinDyn. +! +! Copyright (C) 2012-2016 National Renewable Energy Laboratory +! +! Licensed under the Apache License, Version 2.0 (the "License"); +! you may not use this file except in compliance with the License. +! You may obtain a copy of the License at +! +! http://www.apache.org/licenses/LICENSE-2.0 +! +! Unless required by applicable law or agreed to in writing, software +! distributed under the License is distributed on an "AS IS" BASIS, +! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +! See the License for the specific language governing permissions and +! limitations under the License. +! +! +! W A R N I N G : This file was automatically generated from the FAST registry. Changes made to this file may be lost. +! +!********************************************************************************************************************************* +!> This module contains the user-defined types needed in LinDyn. It also contains copy, destroy, pack, and +!! unpack routines associated with each defined data type. This code is automatically generated by the FAST Registry. +MODULE LinDyn_Types +!--------------------------------------------------------------------------------------------------------------------------------- +USE NWTC_Library +IMPLICIT NONE +! ========= LD_InitInputType ======= + TYPE, PUBLIC :: LD_InitInputType + REAL(DbKi) :: dt = 0.0_R8Ki !< time step [s] + INTEGER(IntKi) :: IntMethod = 0_IntKi !< Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4]) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MM !< Mass matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CC !< Damping matrix [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KK !< Stiffness matrix [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: x0 !< Degrees of freedom initial conditions - shape nx [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: xd0 !< Velocities initial conditions - shape nx [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: activeDOFs !< Degrees of freedom that are active - shape nx [-] + character(8) :: prefix !< Prefix for degrees of freedom write outputs [-] + character(8) , DIMENSION(:), ALLOCATABLE :: DOFsNames !< Names of degrees of freedom for write outputs [-] + character(8) , DIMENSION(:), ALLOCATABLE :: DOFsUnits !< Units of degrees of freedom for write outputs [-] + LOGICAL :: Linearize = .false. !< Flag that tells this module if the glue code wants to linearize. [-] + character(2048) :: PrescribedMotionFile !< Input file for prescribed motion [-] + END TYPE LD_InitInputType +! ======================= +! ========= LD_InitOutputType ======= + TYPE, PUBLIC :: LD_InitOutputType + TYPE(ProgDesc) :: Ver !< This module's name, version, and date [-] + character(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputHdr !< The is the list of all output channel header strings (includes all sub-module channels) [-] + character(ChanLen) , DIMENSION(:), ALLOCATABLE :: WriteOutputUnt !< The is the list of all output channel unit strings (includes all sub-module channels) [-] + character(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_y !< Names of the outputs used in linearization [-] + character(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_x !< Names of the continuous states used in linearization [-] + character(LinChanLen) , DIMENSION(:), ALLOCATABLE :: LinNames_u !< Names of the inputs used in linearization [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_y !< Flag that tells FAST/MBC3 if the outputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_x !< Flag that tells FAST/MBC3 if the continuous states used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: RotFrame_u !< Flag that tells FAST/MBC3 if the inputs used in linearization are in the rotating frame [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: IsLoad_u !< Flag that tells FAST if the inputs used in linearization are loads (for preconditioning matrix) [-] + INTEGER(IntKi) , DIMENSION(:), ALLOCATABLE :: DerivOrder_x !< Integer that tells FAST/MBC3 the maximum derivative order of continuous states used in linearization [-] + END TYPE LD_InitOutputType +! ======================= +! ========= LD_ContinuousStateType ======= + TYPE, PUBLIC :: LD_ContinuousStateType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: q !< Continuous states q =(x,xdot) [-] + END TYPE LD_ContinuousStateType +! ======================= +! ========= LD_DiscreteStateType ======= + TYPE, PUBLIC :: LD_DiscreteStateType + REAL(SiKi) :: Dummy = 0.0_R4Ki !< [-] + END TYPE LD_DiscreteStateType +! ======================= +! ========= LD_ConstraintStateType ======= + TYPE, PUBLIC :: LD_ConstraintStateType + REAL(SiKi) :: Dummy = 0.0_R4Ki !< [-] + END TYPE LD_ConstraintStateType +! ======================= +! ========= LD_OtherStateType ======= + TYPE, PUBLIC :: LD_OtherStateType + TYPE(LD_ContinuousStateType) , DIMENSION(:), ALLOCATABLE :: xdot !< Previous state derivs for m-step time integrator [-] + INTEGER(IntKi) :: n = 0_IntKi !< Tracks time step for which OtherState was updated last [-] + INTEGER(IntKi) :: iMotionInterpLast = 1 !< Last index used to interpolate the presribed motion time series [-] + END TYPE LD_OtherStateType +! ======================= +! ========= LD_MiscVarType ======= + TYPE, PUBLIC :: LD_MiscVarType + LOGICAL :: Dummy = .false. !< [-] + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: qPrescribed !< Prescribed motion/velocity/accelerations for all degrees of freedom at a given time [-] + END TYPE LD_MiscVarType +! ======================= +! ========= LD_ParameterType ======= + TYPE, PUBLIC :: LD_ParameterType + REAL(DbKi) :: dt = 0.0_R8Ki !< time step [s] + INTEGER(IntKi) :: IntMethod = 0_IntKi !< Identifier for integration method (1 [RK4], 2 [AB4], or 3 [ABM4]) [-] + INTEGER(IntKi) :: nx = 0_IntKi !< Number of degrees of freedom (size of M) [-] + INTEGER(IntKi) :: nq = 0_IntKi !< nq=2*nx [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: MM !< Mass Matrix - shape (nx x nx) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: CC !< Damping Matrix - shape (nx x nx) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: KK !< Stiffness Matrix - shape (nx x nx) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: Minv !< Inverse of Mass matrix [-] + LOGICAL , DIMENSION(:), ALLOCATABLE :: activeDOFs !< Degrees of freedom that are active [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: AA !< State matrix A - shape (nq x nq) [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BB !< State matrix B - shape (nq x nx) [-] + INTEGER(IntKi) :: NumOuts = 0_IntKi !< Number of values in WriteOutput [-] + TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] + INTEGER(IntKi) , DIMENSION(:,:), ALLOCATABLE :: OutParamLinIndx !< Index into WriteOutput for linearization analysis [-] + REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: PrescribedValues !< Prescribed motion for all degrees of freedom [-] + END TYPE LD_ParameterType +! ======================= +! ========= LD_InputType ======= + TYPE, PUBLIC :: LD_InputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: Fext !< External loads - shape nx [-] + END TYPE LD_InputType +! ======================= +! ========= LD_OutputType ======= + TYPE, PUBLIC :: LD_OutputType + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: xdd + REAL(ReKi) , DIMENSION(:), ALLOCATABLE :: WriteOutput !< outputs to be written to a file [-] + END TYPE LD_OutputType +! ======================= +CONTAINS + +subroutine LD_CopyInitInput(SrcInitInputData, DstInitInputData, CtrlCode, ErrStat, ErrMsg) + type(LD_InitInputType), intent(in) :: SrcInitInputData + type(LD_InitInputType), intent(inout) :: DstInitInputData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: LB(2), UB(2) + integer(IntKi) :: ErrStat2 + character(*), parameter :: RoutineName = 'LD_CopyInitInput' + ErrStat = ErrID_None + ErrMsg = '' + DstInitInputData%dt = SrcInitInputData%dt + DstInitInputData%IntMethod = SrcInitInputData%IntMethod + if (allocated(SrcInitInputData%MM)) then + LB(1:2) = lbound(SrcInitInputData%MM, kind=B8Ki) + UB(1:2) = ubound(SrcInitInputData%MM, kind=B8Ki) + if (.not. allocated(DstInitInputData%MM)) then + allocate(DstInitInputData%MM(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%MM.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%MM = SrcInitInputData%MM + end if + if (allocated(SrcInitInputData%CC)) then + LB(1:2) = lbound(SrcInitInputData%CC, kind=B8Ki) + UB(1:2) = ubound(SrcInitInputData%CC, kind=B8Ki) + if (.not. allocated(DstInitInputData%CC)) then + allocate(DstInitInputData%CC(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%CC.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%CC = SrcInitInputData%CC + end if + if (allocated(SrcInitInputData%KK)) then + LB(1:2) = lbound(SrcInitInputData%KK, kind=B8Ki) + UB(1:2) = ubound(SrcInitInputData%KK, kind=B8Ki) + if (.not. allocated(DstInitInputData%KK)) then + allocate(DstInitInputData%KK(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%KK.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%KK = SrcInitInputData%KK + end if + if (allocated(SrcInitInputData%x0)) then + LB(1:1) = lbound(SrcInitInputData%x0, kind=B8Ki) + UB(1:1) = ubound(SrcInitInputData%x0, kind=B8Ki) + if (.not. allocated(DstInitInputData%x0)) then + allocate(DstInitInputData%x0(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%x0.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%x0 = SrcInitInputData%x0 + end if + if (allocated(SrcInitInputData%xd0)) then + LB(1:1) = lbound(SrcInitInputData%xd0, kind=B8Ki) + UB(1:1) = ubound(SrcInitInputData%xd0, kind=B8Ki) + if (.not. allocated(DstInitInputData%xd0)) then + allocate(DstInitInputData%xd0(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%xd0.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%xd0 = SrcInitInputData%xd0 + end if + if (allocated(SrcInitInputData%activeDOFs)) then + LB(1:1) = lbound(SrcInitInputData%activeDOFs, kind=B8Ki) + UB(1:1) = ubound(SrcInitInputData%activeDOFs, kind=B8Ki) + if (.not. allocated(DstInitInputData%activeDOFs)) then + allocate(DstInitInputData%activeDOFs(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%activeDOFs.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%activeDOFs = SrcInitInputData%activeDOFs + end if + DstInitInputData%prefix = SrcInitInputData%prefix + if (allocated(SrcInitInputData%DOFsNames)) then + LB(1:1) = lbound(SrcInitInputData%DOFsNames, kind=B8Ki) + UB(1:1) = ubound(SrcInitInputData%DOFsNames, kind=B8Ki) + if (.not. allocated(DstInitInputData%DOFsNames)) then + allocate(DstInitInputData%DOFsNames(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%DOFsNames.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%DOFsNames = SrcInitInputData%DOFsNames + end if + if (allocated(SrcInitInputData%DOFsUnits)) then + LB(1:1) = lbound(SrcInitInputData%DOFsUnits, kind=B8Ki) + UB(1:1) = ubound(SrcInitInputData%DOFsUnits, kind=B8Ki) + if (.not. allocated(DstInitInputData%DOFsUnits)) then + allocate(DstInitInputData%DOFsUnits(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitInputData%DOFsUnits.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitInputData%DOFsUnits = SrcInitInputData%DOFsUnits + end if + DstInitInputData%Linearize = SrcInitInputData%Linearize + DstInitInputData%PrescribedMotionFile = SrcInitInputData%PrescribedMotionFile +end subroutine + +subroutine LD_DestroyInitInput(InitInputData, ErrStat, ErrMsg) + type(LD_InitInputType), intent(inout) :: InitInputData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_DestroyInitInput' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(InitInputData%MM)) then + deallocate(InitInputData%MM) + end if + if (allocated(InitInputData%CC)) then + deallocate(InitInputData%CC) + end if + if (allocated(InitInputData%KK)) then + deallocate(InitInputData%KK) + end if + if (allocated(InitInputData%x0)) then + deallocate(InitInputData%x0) + end if + if (allocated(InitInputData%xd0)) then + deallocate(InitInputData%xd0) + end if + if (allocated(InitInputData%activeDOFs)) then + deallocate(InitInputData%activeDOFs) + end if + if (allocated(InitInputData%DOFsNames)) then + deallocate(InitInputData%DOFsNames) + end if + if (allocated(InitInputData%DOFsUnits)) then + deallocate(InitInputData%DOFsUnits) + end if +end subroutine + +subroutine LD_PackInitInput(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_InitInputType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackInitInput' + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%dt) + call RegPack(RF, InData%IntMethod) + call RegPackAlloc(RF, InData%MM) + call RegPackAlloc(RF, InData%CC) + call RegPackAlloc(RF, InData%KK) + call RegPackAlloc(RF, InData%x0) + call RegPackAlloc(RF, InData%xd0) + call RegPackAlloc(RF, InData%activeDOFs) + call RegPack(RF, InData%prefix) + call RegPackAlloc(RF, InData%DOFsNames) + call RegPackAlloc(RF, InData%DOFsUnits) + call RegPack(RF, InData%Linearize) + call RegPack(RF, InData%PrescribedMotionFile) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackInitInput(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_InitInputType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackInitInput' + integer(B8Ki) :: LB(2), UB(2) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%dt); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%IntMethod); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%MM); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%CC); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%KK); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%x0); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%xd0); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%activeDOFs); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%prefix); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%DOFsNames); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%DOFsUnits); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%Linearize); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%PrescribedMotionFile); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyInitOutput(SrcInitOutputData, DstInitOutputData, CtrlCode, ErrStat, ErrMsg) + type(LD_InitOutputType), intent(in) :: SrcInitOutputData + type(LD_InitOutputType), intent(inout) :: DstInitOutputData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'LD_CopyInitOutput' + ErrStat = ErrID_None + ErrMsg = '' + call NWTC_Library_CopyProgDesc(SrcInitOutputData%Ver, DstInitOutputData%Ver, CtrlCode, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + if (allocated(SrcInitOutputData%WriteOutputHdr)) then + LB(1:1) = lbound(SrcInitOutputData%WriteOutputHdr, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%WriteOutputHdr, kind=B8Ki) + if (.not. allocated(DstInitOutputData%WriteOutputHdr)) then + allocate(DstInitOutputData%WriteOutputHdr(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputHdr.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%WriteOutputHdr = SrcInitOutputData%WriteOutputHdr + end if + if (allocated(SrcInitOutputData%WriteOutputUnt)) then + LB(1:1) = lbound(SrcInitOutputData%WriteOutputUnt, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%WriteOutputUnt, kind=B8Ki) + if (.not. allocated(DstInitOutputData%WriteOutputUnt)) then + allocate(DstInitOutputData%WriteOutputUnt(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%WriteOutputUnt.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%WriteOutputUnt = SrcInitOutputData%WriteOutputUnt + end if + if (allocated(SrcInitOutputData%LinNames_y)) then + LB(1:1) = lbound(SrcInitOutputData%LinNames_y, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%LinNames_y, kind=B8Ki) + if (.not. allocated(DstInitOutputData%LinNames_y)) then + allocate(DstInitOutputData%LinNames_y(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_y.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%LinNames_y = SrcInitOutputData%LinNames_y + end if + if (allocated(SrcInitOutputData%LinNames_x)) then + LB(1:1) = lbound(SrcInitOutputData%LinNames_x, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%LinNames_x, kind=B8Ki) + if (.not. allocated(DstInitOutputData%LinNames_x)) then + allocate(DstInitOutputData%LinNames_x(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_x.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%LinNames_x = SrcInitOutputData%LinNames_x + end if + if (allocated(SrcInitOutputData%LinNames_u)) then + LB(1:1) = lbound(SrcInitOutputData%LinNames_u, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%LinNames_u, kind=B8Ki) + if (.not. allocated(DstInitOutputData%LinNames_u)) then + allocate(DstInitOutputData%LinNames_u(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%LinNames_u.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%LinNames_u = SrcInitOutputData%LinNames_u + end if + if (allocated(SrcInitOutputData%RotFrame_y)) then + LB(1:1) = lbound(SrcInitOutputData%RotFrame_y, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%RotFrame_y, kind=B8Ki) + if (.not. allocated(DstInitOutputData%RotFrame_y)) then + allocate(DstInitOutputData%RotFrame_y(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_y.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%RotFrame_y = SrcInitOutputData%RotFrame_y + end if + if (allocated(SrcInitOutputData%RotFrame_x)) then + LB(1:1) = lbound(SrcInitOutputData%RotFrame_x, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%RotFrame_x, kind=B8Ki) + if (.not. allocated(DstInitOutputData%RotFrame_x)) then + allocate(DstInitOutputData%RotFrame_x(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_x.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%RotFrame_x = SrcInitOutputData%RotFrame_x + end if + if (allocated(SrcInitOutputData%RotFrame_u)) then + LB(1:1) = lbound(SrcInitOutputData%RotFrame_u, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%RotFrame_u, kind=B8Ki) + if (.not. allocated(DstInitOutputData%RotFrame_u)) then + allocate(DstInitOutputData%RotFrame_u(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%RotFrame_u.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%RotFrame_u = SrcInitOutputData%RotFrame_u + end if + if (allocated(SrcInitOutputData%IsLoad_u)) then + LB(1:1) = lbound(SrcInitOutputData%IsLoad_u, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%IsLoad_u, kind=B8Ki) + if (.not. allocated(DstInitOutputData%IsLoad_u)) then + allocate(DstInitOutputData%IsLoad_u(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%IsLoad_u.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%IsLoad_u = SrcInitOutputData%IsLoad_u + end if + if (allocated(SrcInitOutputData%DerivOrder_x)) then + LB(1:1) = lbound(SrcInitOutputData%DerivOrder_x, kind=B8Ki) + UB(1:1) = ubound(SrcInitOutputData%DerivOrder_x, kind=B8Ki) + if (.not. allocated(DstInitOutputData%DerivOrder_x)) then + allocate(DstInitOutputData%DerivOrder_x(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInitOutputData%DerivOrder_x.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInitOutputData%DerivOrder_x = SrcInitOutputData%DerivOrder_x + end if +end subroutine + +subroutine LD_DestroyInitOutput(InitOutputData, ErrStat, ErrMsg) + type(LD_InitOutputType), intent(inout) :: InitOutputData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'LD_DestroyInitOutput' + ErrStat = ErrID_None + ErrMsg = '' + call NWTC_Library_DestroyProgDesc(InitOutputData%Ver, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (allocated(InitOutputData%WriteOutputHdr)) then + deallocate(InitOutputData%WriteOutputHdr) + end if + if (allocated(InitOutputData%WriteOutputUnt)) then + deallocate(InitOutputData%WriteOutputUnt) + end if + if (allocated(InitOutputData%LinNames_y)) then + deallocate(InitOutputData%LinNames_y) + end if + if (allocated(InitOutputData%LinNames_x)) then + deallocate(InitOutputData%LinNames_x) + end if + if (allocated(InitOutputData%LinNames_u)) then + deallocate(InitOutputData%LinNames_u) + end if + if (allocated(InitOutputData%RotFrame_y)) then + deallocate(InitOutputData%RotFrame_y) + end if + if (allocated(InitOutputData%RotFrame_x)) then + deallocate(InitOutputData%RotFrame_x) + end if + if (allocated(InitOutputData%RotFrame_u)) then + deallocate(InitOutputData%RotFrame_u) + end if + if (allocated(InitOutputData%IsLoad_u)) then + deallocate(InitOutputData%IsLoad_u) + end if + if (allocated(InitOutputData%DerivOrder_x)) then + deallocate(InitOutputData%DerivOrder_x) + end if +end subroutine + +subroutine LD_PackInitOutput(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_InitOutputType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackInitOutput' + if (RF%ErrStat >= AbortErrLev) return + call NWTC_Library_PackProgDesc(RF, InData%Ver) + call RegPackAlloc(RF, InData%WriteOutputHdr) + call RegPackAlloc(RF, InData%WriteOutputUnt) + call RegPackAlloc(RF, InData%LinNames_y) + call RegPackAlloc(RF, InData%LinNames_x) + call RegPackAlloc(RF, InData%LinNames_u) + call RegPackAlloc(RF, InData%RotFrame_y) + call RegPackAlloc(RF, InData%RotFrame_x) + call RegPackAlloc(RF, InData%RotFrame_u) + call RegPackAlloc(RF, InData%IsLoad_u) + call RegPackAlloc(RF, InData%DerivOrder_x) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackInitOutput(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_InitOutputType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackInitOutput' + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + call NWTC_Library_UnpackProgDesc(RF, OutData%Ver) ! Ver + call RegUnpackAlloc(RF, OutData%WriteOutputHdr); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%WriteOutputUnt); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%LinNames_y); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%LinNames_x); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%LinNames_u); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%RotFrame_y); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%RotFrame_x); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%RotFrame_u); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%IsLoad_u); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%DerivOrder_x); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyContState(SrcContStateData, DstContStateData, CtrlCode, ErrStat, ErrMsg) + type(LD_ContinuousStateType), intent(in) :: SrcContStateData + type(LD_ContinuousStateType), intent(inout) :: DstContStateData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: ErrStat2 + character(*), parameter :: RoutineName = 'LD_CopyContState' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(SrcContStateData%q)) then + LB(1:1) = lbound(SrcContStateData%q, kind=B8Ki) + UB(1:1) = ubound(SrcContStateData%q, kind=B8Ki) + if (.not. allocated(DstContStateData%q)) then + allocate(DstContStateData%q(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstContStateData%q.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstContStateData%q = SrcContStateData%q + end if +end subroutine + +subroutine LD_DestroyContState(ContStateData, ErrStat, ErrMsg) + type(LD_ContinuousStateType), intent(inout) :: ContStateData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_DestroyContState' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(ContStateData%q)) then + deallocate(ContStateData%q) + end if +end subroutine + +subroutine LD_PackContState(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_ContinuousStateType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackContState' + if (RF%ErrStat >= AbortErrLev) return + call RegPackAlloc(RF, InData%q) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackContState(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_ContinuousStateType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackContState' + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + call RegUnpackAlloc(RF, OutData%q); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyDiscState(SrcDiscStateData, DstDiscStateData, CtrlCode, ErrStat, ErrMsg) + type(LD_DiscreteStateType), intent(in) :: SrcDiscStateData + type(LD_DiscreteStateType), intent(inout) :: DstDiscStateData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_CopyDiscState' + ErrStat = ErrID_None + ErrMsg = '' + DstDiscStateData%Dummy = SrcDiscStateData%Dummy +end subroutine + +subroutine LD_DestroyDiscState(DiscStateData, ErrStat, ErrMsg) + type(LD_DiscreteStateType), intent(inout) :: DiscStateData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_DestroyDiscState' + ErrStat = ErrID_None + ErrMsg = '' +end subroutine + +subroutine LD_PackDiscState(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_DiscreteStateType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackDiscState' + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%Dummy) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackDiscState(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_DiscreteStateType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackDiscState' + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%Dummy); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyConstrState(SrcConstrStateData, DstConstrStateData, CtrlCode, ErrStat, ErrMsg) + type(LD_ConstraintStateType), intent(in) :: SrcConstrStateData + type(LD_ConstraintStateType), intent(inout) :: DstConstrStateData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_CopyConstrState' + ErrStat = ErrID_None + ErrMsg = '' + DstConstrStateData%Dummy = SrcConstrStateData%Dummy +end subroutine + +subroutine LD_DestroyConstrState(ConstrStateData, ErrStat, ErrMsg) + type(LD_ConstraintStateType), intent(inout) :: ConstrStateData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_DestroyConstrState' + ErrStat = ErrID_None + ErrMsg = '' +end subroutine + +subroutine LD_PackConstrState(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_ConstraintStateType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackConstrState' + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%Dummy) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackConstrState(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_ConstraintStateType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackConstrState' + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%Dummy); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyOtherState(SrcOtherStateData, DstOtherStateData, CtrlCode, ErrStat, ErrMsg) + type(LD_OtherStateType), intent(in) :: SrcOtherStateData + type(LD_OtherStateType), intent(inout) :: DstOtherStateData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: i1 + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'LD_CopyOtherState' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(SrcOtherStateData%xdot)) then + LB(1:1) = lbound(SrcOtherStateData%xdot, kind=B8Ki) + UB(1:1) = ubound(SrcOtherStateData%xdot, kind=B8Ki) + if (.not. allocated(DstOtherStateData%xdot)) then + allocate(DstOtherStateData%xdot(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstOtherStateData%xdot.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + do i1 = LB(1), UB(1) + call LD_CopyContState(SrcOtherStateData%xdot(i1), DstOtherStateData%xdot(i1), CtrlCode, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end do + end if + DstOtherStateData%n = SrcOtherStateData%n + DstOtherStateData%iMotionInterpLast = SrcOtherStateData%iMotionInterpLast +end subroutine + +subroutine LD_DestroyOtherState(OtherStateData, ErrStat, ErrMsg) + type(LD_OtherStateType), intent(inout) :: OtherStateData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: i1 + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'LD_DestroyOtherState' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(OtherStateData%xdot)) then + LB(1:1) = lbound(OtherStateData%xdot, kind=B8Ki) + UB(1:1) = ubound(OtherStateData%xdot, kind=B8Ki) + do i1 = LB(1), UB(1) + call LD_DestroyContState(OtherStateData%xdot(i1), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end do + deallocate(OtherStateData%xdot) + end if +end subroutine + +subroutine LD_PackOtherState(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_OtherStateType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackOtherState' + integer(B8Ki) :: i1 + integer(B8Ki) :: LB(1), UB(1) + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, allocated(InData%xdot)) + if (allocated(InData%xdot)) then + call RegPackBounds(RF, 1, lbound(InData%xdot, kind=B8Ki), ubound(InData%xdot, kind=B8Ki)) + LB(1:1) = lbound(InData%xdot, kind=B8Ki) + UB(1:1) = ubound(InData%xdot, kind=B8Ki) + do i1 = LB(1), UB(1) + call LD_PackContState(RF, InData%xdot(i1)) + end do + end if + call RegPack(RF, InData%n) + call RegPack(RF, InData%iMotionInterpLast) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackOtherState(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_OtherStateType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackOtherState' + integer(B8Ki) :: i1 + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + if (allocated(OutData%xdot)) deallocate(OutData%xdot) + call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return + if (IsAllocAssoc) then + call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return + allocate(OutData%xdot(LB(1):UB(1)),stat=stat) + if (stat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%xdot.', RF%ErrStat, RF%ErrMsg, RoutineName) + return + end if + do i1 = LB(1), UB(1) + call LD_UnpackContState(RF, OutData%xdot(i1)) ! xdot + end do + end if + call RegUnpack(RF, OutData%n); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%iMotionInterpLast); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyMisc(SrcMiscData, DstMiscData, CtrlCode, ErrStat, ErrMsg) + type(LD_MiscVarType), intent(in) :: SrcMiscData + type(LD_MiscVarType), intent(inout) :: DstMiscData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: ErrStat2 + character(*), parameter :: RoutineName = 'LD_CopyMisc' + ErrStat = ErrID_None + ErrMsg = '' + DstMiscData%Dummy = SrcMiscData%Dummy + if (allocated(SrcMiscData%qPrescribed)) then + LB(1:1) = lbound(SrcMiscData%qPrescribed, kind=B8Ki) + UB(1:1) = ubound(SrcMiscData%qPrescribed, kind=B8Ki) + if (.not. allocated(DstMiscData%qPrescribed)) then + allocate(DstMiscData%qPrescribed(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstMiscData%qPrescribed.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstMiscData%qPrescribed = SrcMiscData%qPrescribed + end if +end subroutine + +subroutine LD_DestroyMisc(MiscData, ErrStat, ErrMsg) + type(LD_MiscVarType), intent(inout) :: MiscData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_DestroyMisc' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(MiscData%qPrescribed)) then + deallocate(MiscData%qPrescribed) + end if +end subroutine + +subroutine LD_PackMisc(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_MiscVarType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackMisc' + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%Dummy) + call RegPackAlloc(RF, InData%qPrescribed) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackMisc(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_MiscVarType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackMisc' + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%Dummy); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%qPrescribed); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) + type(LD_ParameterType), intent(in) :: SrcParamData + type(LD_ParameterType), intent(inout) :: DstParamData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: i1, i2 + integer(B8Ki) :: LB(2), UB(2) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'LD_CopyParam' + ErrStat = ErrID_None + ErrMsg = '' + DstParamData%dt = SrcParamData%dt + DstParamData%IntMethod = SrcParamData%IntMethod + DstParamData%nx = SrcParamData%nx + DstParamData%nq = SrcParamData%nq + if (allocated(SrcParamData%MM)) then + LB(1:2) = lbound(SrcParamData%MM, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%MM, kind=B8Ki) + if (.not. allocated(DstParamData%MM)) then + allocate(DstParamData%MM(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%MM.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%MM = SrcParamData%MM + end if + if (allocated(SrcParamData%CC)) then + LB(1:2) = lbound(SrcParamData%CC, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%CC, kind=B8Ki) + if (.not. allocated(DstParamData%CC)) then + allocate(DstParamData%CC(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%CC.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%CC = SrcParamData%CC + end if + if (allocated(SrcParamData%KK)) then + LB(1:2) = lbound(SrcParamData%KK, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%KK, kind=B8Ki) + if (.not. allocated(DstParamData%KK)) then + allocate(DstParamData%KK(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%KK.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%KK = SrcParamData%KK + end if + if (allocated(SrcParamData%Minv)) then + LB(1:2) = lbound(SrcParamData%Minv, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%Minv, kind=B8Ki) + if (.not. allocated(DstParamData%Minv)) then + allocate(DstParamData%Minv(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%Minv.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%Minv = SrcParamData%Minv + end if + if (allocated(SrcParamData%activeDOFs)) then + LB(1:1) = lbound(SrcParamData%activeDOFs, kind=B8Ki) + UB(1:1) = ubound(SrcParamData%activeDOFs, kind=B8Ki) + if (.not. allocated(DstParamData%activeDOFs)) then + allocate(DstParamData%activeDOFs(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%activeDOFs.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%activeDOFs = SrcParamData%activeDOFs + end if + if (allocated(SrcParamData%AA)) then + LB(1:2) = lbound(SrcParamData%AA, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%AA, kind=B8Ki) + if (.not. allocated(DstParamData%AA)) then + allocate(DstParamData%AA(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%AA.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%AA = SrcParamData%AA + end if + if (allocated(SrcParamData%BB)) then + LB(1:2) = lbound(SrcParamData%BB, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%BB, kind=B8Ki) + if (.not. allocated(DstParamData%BB)) then + allocate(DstParamData%BB(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%BB.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%BB = SrcParamData%BB + end if + DstParamData%NumOuts = SrcParamData%NumOuts + if (allocated(SrcParamData%OutParam)) then + LB(1:1) = lbound(SrcParamData%OutParam, kind=B8Ki) + UB(1:1) = ubound(SrcParamData%OutParam, kind=B8Ki) + if (.not. allocated(DstParamData%OutParam)) then + allocate(DstParamData%OutParam(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParam.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + do i1 = LB(1), UB(1) + call NWTC_Library_CopyOutParmType(SrcParamData%OutParam(i1), DstParamData%OutParam(i1), CtrlCode, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + if (ErrStat >= AbortErrLev) return + end do + end if + if (allocated(SrcParamData%OutParamLinIndx)) then + LB(1:2) = lbound(SrcParamData%OutParamLinIndx, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%OutParamLinIndx, kind=B8Ki) + if (.not. allocated(DstParamData%OutParamLinIndx)) then + allocate(DstParamData%OutParamLinIndx(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%OutParamLinIndx.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%OutParamLinIndx = SrcParamData%OutParamLinIndx + end if + if (allocated(SrcParamData%PrescribedValues)) then + LB(1:2) = lbound(SrcParamData%PrescribedValues, kind=B8Ki) + UB(1:2) = ubound(SrcParamData%PrescribedValues, kind=B8Ki) + if (.not. allocated(DstParamData%PrescribedValues)) then + allocate(DstParamData%PrescribedValues(LB(1):UB(1),LB(2):UB(2)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstParamData%PrescribedValues.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstParamData%PrescribedValues = SrcParamData%PrescribedValues + end if +end subroutine + +subroutine LD_DestroyParam(ParamData, ErrStat, ErrMsg) + type(LD_ParameterType), intent(inout) :: ParamData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: i1, i2 + integer(B8Ki) :: LB(2), UB(2) + integer(IntKi) :: ErrStat2 + character(ErrMsgLen) :: ErrMsg2 + character(*), parameter :: RoutineName = 'LD_DestroyParam' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(ParamData%MM)) then + deallocate(ParamData%MM) + end if + if (allocated(ParamData%CC)) then + deallocate(ParamData%CC) + end if + if (allocated(ParamData%KK)) then + deallocate(ParamData%KK) + end if + if (allocated(ParamData%Minv)) then + deallocate(ParamData%Minv) + end if + if (allocated(ParamData%activeDOFs)) then + deallocate(ParamData%activeDOFs) + end if + if (allocated(ParamData%AA)) then + deallocate(ParamData%AA) + end if + if (allocated(ParamData%BB)) then + deallocate(ParamData%BB) + end if + if (allocated(ParamData%OutParam)) then + LB(1:1) = lbound(ParamData%OutParam, kind=B8Ki) + UB(1:1) = ubound(ParamData%OutParam, kind=B8Ki) + do i1 = LB(1), UB(1) + call NWTC_Library_DestroyOutParmType(ParamData%OutParam(i1), ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + end do + deallocate(ParamData%OutParam) + end if + if (allocated(ParamData%OutParamLinIndx)) then + deallocate(ParamData%OutParamLinIndx) + end if + if (allocated(ParamData%PrescribedValues)) then + deallocate(ParamData%PrescribedValues) + end if +end subroutine + +subroutine LD_PackParam(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_ParameterType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackParam' + integer(B8Ki) :: i1, i2 + integer(B8Ki) :: LB(2), UB(2) + if (RF%ErrStat >= AbortErrLev) return + call RegPack(RF, InData%dt) + call RegPack(RF, InData%IntMethod) + call RegPack(RF, InData%nx) + call RegPack(RF, InData%nq) + call RegPackAlloc(RF, InData%MM) + call RegPackAlloc(RF, InData%CC) + call RegPackAlloc(RF, InData%KK) + call RegPackAlloc(RF, InData%Minv) + call RegPackAlloc(RF, InData%activeDOFs) + call RegPackAlloc(RF, InData%AA) + call RegPackAlloc(RF, InData%BB) + call RegPack(RF, InData%NumOuts) + call RegPack(RF, allocated(InData%OutParam)) + if (allocated(InData%OutParam)) then + call RegPackBounds(RF, 1, lbound(InData%OutParam, kind=B8Ki), ubound(InData%OutParam, kind=B8Ki)) + LB(1:1) = lbound(InData%OutParam, kind=B8Ki) + UB(1:1) = ubound(InData%OutParam, kind=B8Ki) + do i1 = LB(1), UB(1) + call NWTC_Library_PackOutParmType(RF, InData%OutParam(i1)) + end do + end if + call RegPackAlloc(RF, InData%OutParamLinIndx) + call RegPackAlloc(RF, InData%PrescribedValues) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackParam(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_ParameterType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackParam' + integer(B8Ki) :: i1, i2 + integer(B8Ki) :: LB(2), UB(2) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + call RegUnpack(RF, OutData%dt); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%IntMethod); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%nx); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%nq); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%MM); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%CC); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%KK); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%Minv); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%activeDOFs); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%AA); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%BB); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%NumOuts); if (RegCheckErr(RF, RoutineName)) return + if (allocated(OutData%OutParam)) deallocate(OutData%OutParam) + call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return + if (IsAllocAssoc) then + call RegUnpackBounds(RF, 1, LB, UB); if (RegCheckErr(RF, RoutineName)) return + allocate(OutData%OutParam(LB(1):UB(1)),stat=stat) + if (stat /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating OutData%OutParam.', RF%ErrStat, RF%ErrMsg, RoutineName) + return + end if + do i1 = LB(1), UB(1) + call NWTC_Library_UnpackOutParmType(RF, OutData%OutParam(i1)) ! OutParam + end do + end if + call RegUnpackAlloc(RF, OutData%OutParamLinIndx); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%PrescribedValues); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyInput(SrcInputData, DstInputData, CtrlCode, ErrStat, ErrMsg) + type(LD_InputType), intent(in) :: SrcInputData + type(LD_InputType), intent(inout) :: DstInputData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: ErrStat2 + character(*), parameter :: RoutineName = 'LD_CopyInput' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(SrcInputData%Fext)) then + LB(1:1) = lbound(SrcInputData%Fext, kind=B8Ki) + UB(1:1) = ubound(SrcInputData%Fext, kind=B8Ki) + if (.not. allocated(DstInputData%Fext)) then + allocate(DstInputData%Fext(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstInputData%Fext.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstInputData%Fext = SrcInputData%Fext + end if +end subroutine + +subroutine LD_DestroyInput(InputData, ErrStat, ErrMsg) + type(LD_InputType), intent(inout) :: InputData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_DestroyInput' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(InputData%Fext)) then + deallocate(InputData%Fext) + end if +end subroutine + +subroutine LD_PackInput(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_InputType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackInput' + if (RF%ErrStat >= AbortErrLev) return + call RegPackAlloc(RF, InData%Fext) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackInput(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_InputType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackInput' + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + call RegUnpackAlloc(RF, OutData%Fext); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_CopyOutput(SrcOutputData, DstOutputData, CtrlCode, ErrStat, ErrMsg) + type(LD_OutputType), intent(in) :: SrcOutputData + type(LD_OutputType), intent(inout) :: DstOutputData + integer(IntKi), intent(in ) :: CtrlCode + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: ErrStat2 + character(*), parameter :: RoutineName = 'LD_CopyOutput' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(SrcOutputData%xdd)) then + LB(1:1) = lbound(SrcOutputData%xdd, kind=B8Ki) + UB(1:1) = ubound(SrcOutputData%xdd, kind=B8Ki) + if (.not. allocated(DstOutputData%xdd)) then + allocate(DstOutputData%xdd(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%xdd.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstOutputData%xdd = SrcOutputData%xdd + end if + if (allocated(SrcOutputData%WriteOutput)) then + LB(1:1) = lbound(SrcOutputData%WriteOutput, kind=B8Ki) + UB(1:1) = ubound(SrcOutputData%WriteOutput, kind=B8Ki) + if (.not. allocated(DstOutputData%WriteOutput)) then + allocate(DstOutputData%WriteOutput(LB(1):UB(1)), stat=ErrStat2) + if (ErrStat2 /= 0) then + call SetErrStat(ErrID_Fatal, 'Error allocating DstOutputData%WriteOutput.', ErrStat, ErrMsg, RoutineName) + return + end if + end if + DstOutputData%WriteOutput = SrcOutputData%WriteOutput + end if +end subroutine + +subroutine LD_DestroyOutput(OutputData, ErrStat, ErrMsg) + type(LD_OutputType), intent(inout) :: OutputData + integer(IntKi), intent( out) :: ErrStat + character(*), intent( out) :: ErrMsg + character(*), parameter :: RoutineName = 'LD_DestroyOutput' + ErrStat = ErrID_None + ErrMsg = '' + if (allocated(OutputData%xdd)) then + deallocate(OutputData%xdd) + end if + if (allocated(OutputData%WriteOutput)) then + deallocate(OutputData%WriteOutput) + end if +end subroutine + +subroutine LD_PackOutput(RF, Indata) + type(RegFile), intent(inout) :: RF + type(LD_OutputType), intent(in) :: InData + character(*), parameter :: RoutineName = 'LD_PackOutput' + if (RF%ErrStat >= AbortErrLev) return + call RegPackAlloc(RF, InData%xdd) + call RegPackAlloc(RF, InData%WriteOutput) + if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_UnPackOutput(RF, OutData) + type(RegFile), intent(inout) :: RF + type(LD_OutputType), intent(inout) :: OutData + character(*), parameter :: RoutineName = 'LD_UnPackOutput' + integer(B8Ki) :: LB(1), UB(1) + integer(IntKi) :: stat + logical :: IsAllocAssoc + if (RF%ErrStat /= ErrID_None) return + call RegUnpackAlloc(RF, OutData%xdd); if (RegCheckErr(RF, RoutineName)) return + call RegUnpackAlloc(RF, OutData%WriteOutput); if (RegCheckErr(RF, RoutineName)) return +end subroutine + +subroutine LD_Input_ExtrapInterp(u, t, u_out, t_out, ErrStat, ErrMsg) + ! + ! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time + ! values of u (which has values associated with times in t). Order of the interpolation is given by the size of u + ! + ! expressions below based on either + ! + ! f(t) = a + ! f(t) = a + b * t, or + ! f(t) = a + b * t + c * t**2 + ! + ! where a, b and c are determined as the solution to + ! f(t1) = u1, f(t2) = u2, f(t3) = u3 (as appropriate) + ! + !---------------------------------------------------------------------------------------------------------------------------------- + + type(LD_InputType), intent(in) :: u(:) ! Input at t1 > t2 > t3 + real(DbKi), intent(in ) :: t(:) ! Times associated with the Inputs + type(LD_InputType), intent(inout) :: u_out ! Input at tin_out + real(DbKi), intent(in ) :: t_out ! time to be extrap/interp'd to + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + integer(IntKi) :: order ! order of polynomial fit (max 2) + integer(IntKi) :: ErrStat2 ! local errors + character(ErrMsgLen) :: ErrMsg2 ! local errors + character(*), PARAMETER :: RoutineName = 'LD_Input_ExtrapInterp' + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + if (size(t) /= size(u)) then + call SetErrStat(ErrID_Fatal, 'size(t) must equal size(u)', ErrStat, ErrMsg, RoutineName) + return + endif + order = size(u) - 1 + select case (order) + case (0) + call LD_CopyInput(u(1), u_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + case (1) + call LD_Input_ExtrapInterp1(u(1), u(2), t, u_out, t_out, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + case (2) + call LD_Input_ExtrapInterp2(u(1), u(2), u(3), t, u_out, t_out, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + case default + call SetErrStat(ErrID_Fatal, 'size(u) must be less than 4 (order must be less than 3).', ErrStat, ErrMsg, RoutineName) + return + end select +end subroutine + +SUBROUTINE LD_Input_ExtrapInterp1(u1, u2, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = u1, f(t2) = u2 +! +!.................................................................................................................................. + + TYPE(LD_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 + TYPE(LD_InputType), INTENT(IN) :: u2 ! Input at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Inputs + TYPE(LD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'LD_Input_ExtrapInterp1' + REAL(DbKi) :: a1, a2 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + ! 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) + t_out = tin_out - tin(1) + + IF (EqualRealNos(t(1), t(2))) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + ! Calculate weighting factors from Lagrange polynomial + a1 = -(t_out - t(2))/t(2) + a2 = t_out/t(2) + + IF (ALLOCATED(u_out%Fext) .AND. ALLOCATED(u1%Fext)) THEN + u_out%Fext = a1*u1%Fext + a2*u2%Fext + END IF ! check if allocated +END SUBROUTINE + +SUBROUTINE LD_Input_ExtrapInterp2(u1, u2, u3, tin, u_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Input u_out at time t_out, from previous/future time +! values of u (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = u1, f(t2) = u2, f(t3) = u3 +! +!.................................................................................................................................. + + TYPE(LD_InputType), INTENT(IN) :: u1 ! Input at t1 > t2 > t3 + TYPE(LD_InputType), INTENT(IN) :: u2 ! Input at t2 > t3 + TYPE(LD_InputType), INTENT(IN) :: u3 ! Input at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Inputs + TYPE(LD_InputType), INTENT(INOUT) :: u_out ! Input at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Inputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: a1,a2,a3 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'LD_Input_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + ! 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) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ! Calculate Lagrange polynomial coefficients + a1 = (t_out - t(2))*(t_out - t(3))/((t(1) - t(2))*(t(1) - t(3))) + a2 = (t_out - t(1))*(t_out - t(3))/((t(2) - t(1))*(t(2) - t(3))) + a3 = (t_out - t(1))*(t_out - t(2))/((t(3) - t(1))*(t(3) - t(2))) + IF (ALLOCATED(u_out%Fext) .AND. ALLOCATED(u1%Fext)) THEN + u_out%Fext = a1*u1%Fext + a2*u2%Fext + a3*u3%Fext + END IF ! check if allocated +END SUBROUTINE + +subroutine LD_Output_ExtrapInterp(y, t, y_out, t_out, ErrStat, ErrMsg) + ! + ! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time + ! values of y (which has values associated with times in t). Order of the interpolation is given by the size of y + ! + ! expressions below based on either + ! + ! f(t) = a + ! f(t) = a + b * t, or + ! f(t) = a + b * t + c * t**2 + ! + ! where a, b and c are determined as the solution to + ! f(t1) = y1, f(t2) = y2, f(t3) = y3 (as appropriate) + ! + !---------------------------------------------------------------------------------------------------------------------------------- + + type(LD_OutputType), intent(in) :: y(:) ! Output at t1 > t2 > t3 + real(DbKi), intent(in ) :: t(:) ! Times associated with the Outputs + type(LD_OutputType), intent(inout) :: y_out ! Output at tin_out + real(DbKi), intent(in ) :: t_out ! time to be extrap/interp'd to + integer(IntKi), intent( out) :: ErrStat ! Error status of the operation + character(*), intent( out) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + integer(IntKi) :: order ! order of polynomial fit (max 2) + integer(IntKi) :: ErrStat2 ! local errors + character(ErrMsgLen) :: ErrMsg2 ! local errors + character(*), PARAMETER :: RoutineName = 'LD_Output_ExtrapInterp' + + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + if (size(t) /= size(y)) then + call SetErrStat(ErrID_Fatal, 'size(t) must equal size(y)', ErrStat, ErrMsg, RoutineName) + return + endif + order = size(y) - 1 + select case (order) + case (0) + call LD_CopyOutput(y(1), y_out, MESH_UPDATECOPY, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + case (1) + call LD_Output_ExtrapInterp1(y(1), y(2), t, y_out, t_out, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + case (2) + call LD_Output_ExtrapInterp2(y(1), y(2), y(3), t, y_out, t_out, ErrStat2, ErrMsg2) + call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + case default + call SetErrStat(ErrID_Fatal, 'size(y) must be less than 4 (order must be less than 3).', ErrStat, ErrMsg, RoutineName) + return + end select +end subroutine + +SUBROUTINE LD_Output_ExtrapInterp1(y1, y2, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 1. +! +! f(t) = a + b * t, or +! +! where a and b are determined as the solution to +! f(t1) = y1, f(t2) = y2 +! +!.................................................................................................................................. + + TYPE(LD_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 + TYPE(LD_OutputType), INTENT(IN) :: y2 ! Output at t2 + REAL(DbKi), INTENT(IN ) :: tin(2) ! Times associated with the Outputs + TYPE(LD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(2) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + CHARACTER(*), PARAMETER :: RoutineName = 'LD_Output_ExtrapInterp1' + REAL(DbKi) :: a1, a2 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + ! 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) + t_out = tin_out - tin(1) + + IF (EqualRealNos(t(1), t(2))) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg, RoutineName) + RETURN + END IF + + ! Calculate weighting factors from Lagrange polynomial + a1 = -(t_out - t(2))/t(2) + a2 = t_out/t(2) + + IF (ALLOCATED(y_out%xdd) .AND. ALLOCATED(y1%xdd)) THEN + y_out%xdd = a1*y1%xdd + a2*y2%xdd + END IF ! check if allocated + IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN + y_out%WriteOutput = a1*y1%WriteOutput + a2*y2%WriteOutput + END IF ! check if allocated +END SUBROUTINE + +SUBROUTINE LD_Output_ExtrapInterp2(y1, y2, y3, tin, y_out, tin_out, ErrStat, ErrMsg ) +! +! This subroutine calculates a extrapolated (or interpolated) Output y_out at time t_out, from previous/future time +! values of y (which has values associated with times in t). Order of the interpolation is 2. +! +! expressions below based on either +! +! f(t) = a + b * t + c * t**2 +! +! where a, b and c are determined as the solution to +! f(t1) = y1, f(t2) = y2, f(t3) = y3 +! +!.................................................................................................................................. + + TYPE(LD_OutputType), INTENT(IN) :: y1 ! Output at t1 > t2 > t3 + TYPE(LD_OutputType), INTENT(IN) :: y2 ! Output at t2 > t3 + TYPE(LD_OutputType), INTENT(IN) :: y3 ! Output at t3 + REAL(DbKi), INTENT(IN ) :: tin(3) ! Times associated with the Outputs + TYPE(LD_OutputType), INTENT(INOUT) :: y_out ! Output at tin_out + REAL(DbKi), INTENT(IN ) :: tin_out ! time to be extrap/interp'd to + INTEGER(IntKi), INTENT( OUT) :: ErrStat ! Error status of the operation + CHARACTER(*), INTENT( OUT) :: ErrMsg ! Error message if ErrStat /= ErrID_None + ! local variables + REAL(DbKi) :: t(3) ! Times associated with the Outputs + REAL(DbKi) :: t_out ! Time to which to be extrap/interpd + INTEGER(IntKi) :: order ! order of polynomial fit (max 2) + REAL(DbKi) :: a1,a2,a3 ! temporary for extrapolation/interpolation + INTEGER(IntKi) :: ErrStat2 ! local errors + CHARACTER(ErrMsgLen) :: ErrMsg2 ! local errors + CHARACTER(*), PARAMETER :: RoutineName = 'LD_Output_ExtrapInterp2' + INTEGER :: i01 ! dim1 level 0 counter variable for arrays of ddts + INTEGER :: i1 ! dim1 counter variable for arrays + ! Initialize ErrStat + ErrStat = ErrID_None + ErrMsg = '' + ! 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) + t_out = tin_out - tin(1) + + IF ( EqualRealNos( t(1), t(2) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(2) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(2), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(2) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + ELSE IF ( EqualRealNos( t(1), t(3) ) ) THEN + CALL SetErrStat(ErrID_Fatal, 't(1) must not equal t(3) to avoid a division-by-zero error.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + + ! Calculate Lagrange polynomial coefficients + a1 = (t_out - t(2))*(t_out - t(3))/((t(1) - t(2))*(t(1) - t(3))) + a2 = (t_out - t(1))*(t_out - t(3))/((t(2) - t(1))*(t(2) - t(3))) + a3 = (t_out - t(1))*(t_out - t(2))/((t(3) - t(1))*(t(3) - t(2))) + IF (ALLOCATED(y_out%xdd) .AND. ALLOCATED(y1%xdd)) THEN + y_out%xdd = a1*y1%xdd + a2*y2%xdd + a3*y3%xdd + END IF ! check if allocated + IF (ALLOCATED(y_out%WriteOutput) .AND. ALLOCATED(y1%WriteOutput)) THEN + y_out%WriteOutput = a1*y1%WriteOutput + a2*y2%WriteOutput + a3*y3%WriteOutput + END IF ! check if allocated +END SUBROUTINE +END MODULE LinDyn_Types +!ENDOFREGISTRYGENERATEDFILE diff --git a/modules/map/src/mapsys.h b/modules/map/src/mapsys.h index 2f6291c4d7..e8966d6d0e 100644 --- a/modules/map/src/mapsys.h +++ b/modules/map/src/mapsys.h @@ -33,7 +33,7 @@ #if defined(_WIN32) || defined(_WIN64) -# include +# include # include #else # include diff --git a/modules/nwtc-library/CMakeLists.txt b/modules/nwtc-library/CMakeLists.txt index de91776fea..139d67b0ef 100644 --- a/modules/nwtc-library/CMakeLists.txt +++ b/modules/nwtc-library/CMakeLists.txt @@ -160,7 +160,6 @@ add_dependencies(nwtclibs nwtc_library_inc_subs) target_link_libraries(nwtclibs PUBLIC ${LAPACK_LIBRARIES} ${CMAKE_DL_LIBS} - ${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES} ) if (USE_DLL_INTERFACE) target_compile_definitions(nwtclibs PRIVATE USE_DLL_INTERFACE) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 0408b727eb..86a34299b9 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -1850,7 +1850,7 @@ SUBROUTINE DispNVD1 ( ProgInfo, DispNWTCVer ) END IF END IF - CALL WrScr ( 'Running '//TRIM( GetNVD( ProgInfo ) )//'.' ) + CALL WrScr ( ' Running '//TRIM( GetNVD( ProgInfo ) )//'.' ) RETURN END SUBROUTINE DispNVD1 @@ -7789,5 +7789,92 @@ SUBROUTINE WrScr1 ( Str ) RETURN END SUBROUTINE WrScr1 + + !---------------------------------------------------------------------------------------------------------------------------------- + !> Read a delimited file of float with one or multiple lines of header + !! TODO: put me in a CSV.f90 file of the NWTC library + !! TODO: automatic detection of number of columns for instance using ReadCAryFromStr + !! See also the quick and dirty check introduced to read blade files that don't have Buoyancy columns + subroutine ReadDelimFile(Filename, nCol, array, errStat, errMsg, nHeaderLines, priPath) + character(len=*), intent(in) :: Filename + integer(IntKi), intent(in) :: nCol + real(ReKi), dimension(:,:), allocatable, intent(out) :: array + integer(IntKi) , intent(out) :: errStat ! Status of error message + character(*) , intent(out) :: errMsg ! Error message if errStat /= ErrID_None + integer(IntKi), optional, intent(in ) :: nHeaderLines + character(*) , optional, intent(in ) :: priPath ! Primary path, to use if filename is not absolute + integer(IntKi) :: UnIn, i, j, nLine, nHead + character(len= 2048) :: line + integer(IntKi) :: errStat2 ! local status of error message + character(ErrMsgLen) :: errMsg2 ! temporary Error message + character(len=2048) :: Filename_Loc ! filename local to this function + errStat = ErrID_None + errMsg = "" + + Filename_Loc = Filename + if (present(priPath)) then + if (PathIsRelative(Filename_Loc)) Filename_Loc = trim(PriPath)//trim(Filename) + endif + + ! Open file + call GetNewUnit(UnIn) + call OpenFInpFile(UnIn, Filename_Loc, errStat2, errMsg2); if(Failed()) return + ! Count number of lines + nLine = line_count(UnIn, errStat2, errMsg2); if(Failed()) return + if (allocated(array)) deallocate(array) + allocate(array(nLine-1, nCol), stat=errStat2); errMsg2='allocation failed'; if(Failed())return + ! Read header + nHead=1 + if (present(nHeaderLines)) nHead = nHeaderLines + do i=1,nHead + read(UnIn, *, IOSTAT=errStat2) line + errMsg2 = ' Error reading line '//trim(Num2LStr(1))//' of file: '//trim(Filename_Loc) + if(Failed()) return + enddo + ! Read data + do i = 1,nLine-1 + read (UnIn,*,IOSTAT=errStat2) (array(i,j), j=1,nCol) + errMsg2 = ' Error reading line '//trim(Num2LStr(i+1))//' of file: '//trim(Filename_Loc) + if(Failed()) return + end do + close(UnIn) + contains + logical function Failed() + CALL SetErrStat(errStat2, errMsg2, errStat, errMsg, 'ReadDelimFile' ) + Failed = errStat >= AbortErrLev + if (Failed) then + if ((UnIn)>0) close(UnIn) + endif + end function Failed + end subroutine ReadDelimFile + + !---------------------------------------------------------------------------------------------------------------------------------- + !> Counts number of lines in a file, do not count last line if empty + integer function line_count(iUnit, errStat, errMsg) + integer(IntKi), intent(in) :: iUnit + integer(IntKi), intent(out) :: errStat ! Error status + character(*), intent(out) :: errMsg ! Error message associated with ErrStat + character(len=2048) :: line + integer, parameter :: nline_max=100000000 ! 100 M safety for infinite loop.. + integer :: i + errStat = ErrID_None + errMsg = '' + line_count=0 + do i=1,nline_max + line='' + read(iUnit,'(A)',END=100)line + line_count=line_count+1 + enddo + if (line_count==nline_max) then + errStat = ErrID_Fatal + errMsg = 'Error: maximum number of line exceeded for line_count' + return + endif + 100 if(len(trim(line))>0) then + line_count=line_count+1 + endif + rewind(iUnit) + return + end function line_count END MODULE NWTC_IO diff --git a/modules/nwtc-library/src/NWTC_Num.f90 b/modules/nwtc-library/src/NWTC_Num.f90 index 012a6f280a..66148d1e3d 100644 --- a/modules/nwtc-library/src/NWTC_Num.f90 +++ b/modules/nwtc-library/src/NWTC_Num.f90 @@ -3311,6 +3311,44 @@ SUBROUTINE InterpStpMat8( XVal, XAry, Y, Ind, AryLen, yInterp ) RETURN END SUBROUTINE InterpStpMat8 +!======================================================================= +!---------------------------------------------------------------------------------------------------------------------------------- +!> Perform linear interpolation of an array, where first column is assumed to be ascending time values +!! Similar to InterpStpMat, I think (to check), interpTimeValues=InterpStpMat( array(:,1), time, array(:,1:), iLast, AryLen, values ) +!! First value is used for times before, and last value is used for time beyond + subroutine interpTimeValue(array, time, iLast, values) + real(ReKi), dimension(:,:), intent(in) :: array !< Values, shape nt x nc, where array(:,1) is the time vector + real(DbKi), intent(in) :: time !< Time where values are to be interpolated + integer(IntKi), intent(inout) :: iLast !< previous index used (to speed up interpolation) + real(ReKi), dimension(:), intent(out) :: values !< vector of values, shape nc, at given `time` + integer :: i, nMax + real(ReKi) :: alpha + nMax = size(array, 1) + iLast = max( min(iLast, nMax), 1) ! Clip iLast between 1 and nMax + !call InterpStpMat( array(:,1), time, array(:,1:), iLast, AryLen, values ) + if (array(iLast,1) > time) then + values = array(iLast,2:) + elseif (iLast == nMax) then + values = array(iLast,2:) + else + ! Look for index + do i = iLast, nMax + if (array(i,1)<=time) then + iLast=i + else + exit + endif + enddo + if (iLast==nMax) then + values = array(iLast,2:) + else + ! Linear interpolation + alpha = (array(iLast+1,1)-time)/(array(iLast+1,1)-array(iLast,1)) + values = array(iLast,2:)*alpha + array(iLast+1,2:)*(1-alpha) + endif + endif + end subroutine interpTimeValue + !======================================================================= !< This routine linearly interpolates Dataset. It is !! set for a 2-d interpolation on x and y of the input point. @@ -4946,7 +4984,7 @@ FUNCTION RegCubicSplineInterpM ( X, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) RE RETURN END FUNCTION RegCubicSplineInterpM ! ( X, XAry, YAry, DelX, Coef, ErrStat, ErrMsg ) !======================================================================= -!> This routine is used to integrate funciton f over the interval [a, b]. This routine +!> This routine is used to integrate function f over the interval [a, b]. This routine !! is useful for sufficiently smooth (e.g., analytic) integrands, integrated over !! intervals which contain no singularities, and where the endpoints are also nonsingular. !! diff --git a/modules/openfast-library/src/FAST_Library.f90 b/modules/openfast-library/src/FAST_Library.f90 index 82a5d9d96c..ff584af59a 100644 --- a/modules/openfast-library/src/FAST_Library.f90 +++ b/modules/openfast-library/src/FAST_Library.f90 @@ -53,7 +53,7 @@ subroutine FAST_AllocateTurbines(nTurbines, ErrStat_c, ErrMsg_c) BIND (C, NAME=' call wrscr1('Proceeding anyway.') end if - allocate(Turbine(0:NumTurbines-1),Stat=ErrStat) !Allocate in C style because most of the other Turbine properties from the input file are in C style inside the C++ driver + allocate(Turbine(1:NumTurbines),Stat=ErrStat) !Allocate in F style -- all logic inside FAST_Subs is based on index 1 start, not C style index 0 if (ErrStat /= 0) then ErrStat_c = ErrID_Fatal @@ -83,13 +83,13 @@ subroutine FAST_DeallocateTurbines(ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Deal ErrMsg_c = C_NULL_CHAR end subroutine !================================================================================================================================== -subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt_out_c, tmax_c, ErrStat_c, ErrMsg_c, ChannelNames_c, TMax, InitInpAry) BIND (C, NAME='FAST_Sizes') - IMPLICIT NONE +subroutine FAST_Sizes(iTurb_c, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt_out_c, tmax_c, ErrStat_c, ErrMsg_c, ChannelNames_c, TMax, InitInpAry) BIND (C, NAME='FAST_Sizes') + IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Sizes !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Sizes #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c INTEGER(C_INT), INTENT( OUT) :: NumOuts_c @@ -106,8 +106,12 @@ subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt CHARACTER(IntfStrLen) :: InputFileName INTEGER :: i, j, k TYPE(FAST_ExternInitType) :: ExternInitData + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) - ! transfer the character array from C to a Fortran string: + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + + ! transfer the character array from C to a Fortran string: InputFileName = TRANSFER( InputFileName_c, InputFileName ) I = INDEX(InputFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... IF ( I > 0 ) InputFileName = InputFileName(1:I) ! remove it @@ -126,7 +130,7 @@ subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt IF (PRESENT(TMax)) THEN ExternInitData%TMax = TMax END IF - ExternInitData%TurbineID = -1 ! we're not going to use this to simulate a wind farm + ExternInitData%TurbIDforName = -1 ! we're not going to use this to simulate a wind farm ExternInitData%TurbinePos = 0.0_ReKi ! turbine position is at the origin ExternInitData%NumCtrl2SC = 0 ExternInitData%NumSC2Ctrl = 0 @@ -180,29 +184,33 @@ subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, dt end subroutine FAST_Sizes !================================================================================================================================== -subroutine FAST_Start(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Start') - IMPLICIT NONE +subroutine FAST_Start(iTurb_c, NumInputs_c, NumOutputs_c, InputAry, OutputAry, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Start') + IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Start !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Start #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT(IN ) :: NumInputs_c INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) REAL(C_DOUBLE), INTENT( OUT) :: OutputAry(NumOutputs_c) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - + ! local CHARACTER(IntfStrLen) :: InputFileName INTEGER :: i REAL(ReKi) :: Outputs(NumOutputs_c-1) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) INTEGER(IntKi) :: ErrStat2 ! Error status CHARACTER(IntfStrLen-1) :: ErrMsg2 ! Error message (this needs to be static so that it will print in Matlab's mex library) + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + ! initialize variables: n_t_global = 0 @@ -244,13 +252,13 @@ subroutine FAST_Start(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, Err end subroutine FAST_Start !================================================================================================================================== -subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, EndSimulationEarly, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Update') +subroutine FAST_Update(iTurb_c, NumInputs_c, NumOutputs_c, InputAry, OutputAry, EndSimulationEarly, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Update') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Update !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Update #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT(IN ) :: NumInputs_c INTEGER(C_INT), INTENT(IN ) :: NumOutputs_c REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) @@ -262,9 +270,14 @@ subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, En ! local variables REAL(ReKi) :: Outputs(NumOutputs_c-1) INTEGER(IntKi) :: i + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + INTEGER(IntKi) :: ErrStat2 ! Error status CHARACTER(IntfStrLen-1) :: ErrMsg2 ! Error message (this needs to be static so that it will print in Matlab's mex library) + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + EndSimulationEarly = .FALSE. IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish @@ -326,21 +339,25 @@ subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, En end subroutine FAST_Update !================================================================================================================================== ! Get the hub's absolute position, rotation velocity, and orientation DCM for the current time step -subroutine FAST_HubPosition(iTurb, AbsPosition_c, RotationalVel_c, Orientation_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_HubPosition') +subroutine FAST_HubPosition(iTurb_c, AbsPosition_c, RotationalVel_c, Orientation_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_HubPosition') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_HubPosition !GCC$ ATTRIBUTES DLLEXPORT :: FAST_HubPosition #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) REAL(C_FLOAT), INTENT( OUT) :: AbsPosition_c(3), RotationalVel_c(3) REAL(C_DOUBLE), INTENT( OUT) :: Orientation_c(9) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) ErrStat_c = ErrID_None ErrMsg = C_NULL_CHAR + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + if (iTurb > size(Turbine) ) then ErrStat_c = ErrID_Fatal ErrMsg = "iTurb is greater than the number of turbines in the simulation."//C_NULL_CHAR @@ -372,7 +389,7 @@ subroutine FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, m_FAST) IMPLICIT NONE - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(IntKi), INTENT(IN ) :: iTurb ! Turbine number, Fortran indexing (starts at 1 for first turbine) INTEGER(C_INT), INTENT(IN ) :: NumInputs_c REAL(C_DOUBLE), INTENT(IN ) :: InputAry(NumInputs_c) ! Inputs from Simulink TYPE(FAST_MiscVarType), INTENT(INOUT) :: m_FAST ! Miscellaneous variables @@ -399,26 +416,30 @@ subroutine FAST_SetExternalInputs(iTurb, NumInputs_c, InputAry, m_FAST) end subroutine FAST_SetExternalInputs !================================================================================================================================== -subroutine FAST_End(iTurb, StopTheProgram) BIND (C, NAME='FAST_End') +subroutine FAST_End(iTurb_c, StopTheProgram) BIND (C, NAME='FAST_End') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_End !GCC$ ATTRIBUTES DLLEXPORT :: FAST_End #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) LOGICAL(C_BOOL), INTENT(IN) :: StopTheProgram ! flag indicating if the program should end (false if there are more turbines to end) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 CALL ExitThisProgram_T( Turbine(iTurb), ErrID_None, LOGICAL(StopTheProgram)) end subroutine FAST_End !================================================================================================================================== -subroutine FAST_CreateCheckpoint(iTurb, CheckpointRootName_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CreateCheckpoint') +subroutine FAST_CreateCheckpoint(iTurb_c, CheckpointRootName_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CreateCheckpoint') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_CreateCheckpoint !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CreateCheckpoint #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) @@ -427,9 +448,12 @@ subroutine FAST_CreateCheckpoint(iTurb, CheckpointRootName_c, ErrStat_c, ErrMsg_ CHARACTER(IntfStrLen) :: CheckpointRootName INTEGER(IntKi) :: I INTEGER(IntKi) :: Unit + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 - ! transfer the character array from C to a Fortran string: + ! transfer the character array from C to a Fortran string: CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) I = INDEX(CheckpointRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... IF ( I > 0 ) CheckpointRootName = CheckpointRootName(1:I) ! remove it @@ -454,13 +478,13 @@ subroutine FAST_CreateCheckpoint(iTurb, CheckpointRootName_c, ErrStat_c, ErrMsg_ end subroutine FAST_CreateCheckpoint !================================================================================================================================== -subroutine FAST_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, NumOuts_c, dt_c, n_t_global_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Restart') +subroutine FAST_Restart(iTurb_c, CheckpointRootName_c, AbortErrLev_c, NumOuts_c, dt_c, n_t_global_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Restart') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_Restart !GCC$ ATTRIBUTES DLLEXPORT :: FAST_Restart #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c INTEGER(C_INT), INTENT( OUT) :: NumOuts_c @@ -475,8 +499,11 @@ subroutine FAST_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, NumOuts_c, d INTEGER(IntKi) :: Unit REAL(DbKi) :: t_initial_out INTEGER(IntKi) :: NumTurbines_out - CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 ! transfer the character array from C to a Fortran string: CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) @@ -508,19 +535,18 @@ subroutine FAST_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, NumOuts_c, d end subroutine FAST_Restart !================================================================================================================================== -subroutine FAST_ExtLoads_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c, TurbPosn, AbortErrLev_c, dtDriver_c, dt_c, NumBl_c, & +subroutine FAST_ExtLoads_Init(iTurb_c, TMax, InputFileName_c, TurbIDforName, OutFileRoot_c, TurbPosn, AbortErrLev_c, dtDriver_c, dt_c, NumBl_c, & az_blend_mean_c, az_blend_delta_c, vel_mean_c, wind_dir_c, z_ref_c, shear_exp_c, & ExtLd_Input_from_FAST, ExtLd_Parameter_from_FAST, ExtLd_Output_to_FAST, SC_DX_Input_from_FAST, SC_DX_Output_to_FAST, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_ExtLoads_Init') -!DEC$ ATTRIBUTES DLLEXPORT::FAST_ExtLoads_Init IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_ExtLoads_Init !GCC$ ATTRIBUTES DLLEXPORT :: FAST_ExtLoads_Init #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) REAL(C_DOUBLE), INTENT(IN ) :: TMax CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) - INTEGER(C_INT), INTENT(IN ) :: TurbID ! Need not be same as iTurb + INTEGER(C_INT), INTENT(IN ) :: TurbIDforName ! Need not be same as iTurb CHARACTER(KIND=C_CHAR), INTENT( OUT) :: OutFileRoot_c(IntfStrLen) REAL(C_FLOAT), INTENT(IN ) :: TurbPosn(3) REAL(C_DOUBLE), INTENT(IN ) :: dtDriver_c @@ -546,9 +572,12 @@ subroutine FAST_ExtLoads_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_ INTEGER(C_INT) :: i TYPE(FAST_ExternInitType) :: ExternInitData INTEGER(IntKi) :: CompLoadsType - + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) CHARACTER(*), PARAMETER :: RoutineName = 'FAST_ExtLoads_Init' + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + ! transfer the character array from C to a Fortran string: InputFileName = TRANSFER( InputFileName_c, InputFileName ) I = INDEX(InputFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... @@ -560,7 +589,7 @@ subroutine FAST_ExtLoads_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_ ErrMsg = "" ExternInitData%TMax = TMax - ExternInitData%TurbineID = TurbID + ExternInitData%TurbIDforName = TurbIDforName ExternInitData%TurbinePos = TurbPosn ExternInitData%SensorType = SensorType_None ExternInitData%NumSC2CtrlGlob = 0 @@ -607,17 +636,19 @@ subroutine FAST_ExtLoads_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_ end subroutine FAST_ExtLoads_Init !================================================================================================================================== -subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c, NumSC2CtrlGlob, NumSC2Ctrl, NumCtrl2SC, InitSCOutputsGlob, InitSCOutputsTurbine, NumActForcePtsBlade, NumActForcePtsTower, TurbPosn, AbortErrLev_c, dtDriver_c, dt_c, InflowType, NumBl_c, NumBlElem_c, NumTwrElem_c, NodeClusterType_c, & - ExtInfw_Input_from_FAST, ExtInfw_Output_to_FAST, SC_DX_Input_from_FAST, SC_DX_Output_to_FAST, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_ExtInfw_Init') +subroutine FAST_ExtInfw_Init(iTurb_c, TMax, InputFileName_c, TurbIDforName, OutFileRoot_c, NumSC2CtrlGlob, NumSC2Ctrl, NumCtrl2SC, & + InitSCOutputsGlob, InitSCOutputsTurbine, NumActForcePtsBlade, NumActForcePtsTower, TurbPosn, AbortErrLev_c, & + dtDriver_c, dt_c, InflowType, NumBl_c, NumBlElem_c, NumTwrElem_c, NodeClusterType_c, & + ExtInfw_Input_from_FAST, ExtInfw_Output_to_FAST, SC_DX_Input_from_FAST, SC_DX_Output_to_FAST, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_ExtInfw_Init') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Init !GCC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Init #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number REAL(C_DOUBLE), INTENT(IN ) :: TMax CHARACTER(KIND=C_CHAR), INTENT(IN ) :: InputFileName_c(IntfStrLen) - INTEGER(C_INT), INTENT(IN ) :: TurbID ! Need not be same as iTurb + INTEGER(C_INT), INTENT(IN ) :: TurbIDforName ! Need not be same as iTurb_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: OutFileRoot_c(IntfStrLen) ! Root of output and restart file name INTEGER(C_INT), INTENT(IN ) :: NumSC2CtrlGlob ! Supercontroller global outputs = controller global inputs INTEGER(C_INT), INTENT(IN ) :: NumSC2Ctrl ! Supercontroller outputs = controller inputs @@ -646,9 +677,13 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c CHARACTER(IntfStrLen) :: InputFileName INTEGER(C_INT) :: i TYPE(FAST_ExternInitType) :: ExternInitData + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) CHARACTER(*), PARAMETER :: RoutineName = 'FAST_ExtInfw_Init' + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + ! transfer the character array from C to a Fortran string: InputFileName = TRANSFER( InputFileName_c, InputFileName ) I = INDEX(InputFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end... @@ -662,8 +697,15 @@ subroutine FAST_ExtInfw_Init(iTurb, TMax, InputFileName_c, TurbID, OutFileRoot_c NumBl_c = 0 ! initialize here in case of error NumBlElem_c = 0 ! initialize here in case of error + ! Check TurbIDforName -- must be 0 or larger + if (TurbIDforName < 0) then + ErrStat = ErrID_Fatal + ErrMsg = "TurbIDforName cannot be negative" + if (Failed()) return + endif + ExternInitData%TMax = TMax - ExternInitData%TurbineID = TurbID + ExternInitData%TurbIDforName = TurbIDforName ExternInitData%TurbinePos = TurbPosn ExternInitData%SensorType = SensorType_None ExternInitData%NumCtrl2SC = NumCtrl2SC @@ -783,18 +825,22 @@ END FUNCTION FAILED end subroutine !================================================================================================================================== -subroutine FAST_CFD_Solution0(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Solution0') +subroutine FAST_CFD_Solution0(iTurb_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Solution0') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Solution0 !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Solution0 #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) CHARACTER(*), PARAMETER :: RoutineName = 'FAST_CFD_Solution0' + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + call FAST_Solution0_T(Turbine(iTurb), ErrStat, ErrMsg ) ! if(Turbine(iTurb)%SC_DX%p%useSC) then @@ -808,15 +854,19 @@ subroutine FAST_CFD_Solution0(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CF end subroutine FAST_CFD_Solution0 !================================================================================================================================== -subroutine FAST_CFD_InitIOarrays_SubStep(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_InitIOarrays_SubStep') -!DEC$ ATTRIBUTES DLLEXPORT::FAST_CFD_InitIOarrays_SubStep +subroutine FAST_CFD_InitIOarrays_SubStep(iTurb_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_InitIOarrays_SubStep') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_InitIOarrays_SubStep !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_InitIOarrays_SubStep #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 call FAST_InitIOarrays_SubStep_T(t_initial, Turbine(iTurb), ErrStat, ErrMsg ) @@ -827,14 +877,14 @@ subroutine FAST_CFD_InitIOarrays_SubStep(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NA end subroutine FAST_CFD_InitIOarrays_SubStep !================================================================================================================================== -subroutine FAST_ExtInfw_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, dt_c, numblades_c, numElementsPerBlade_c, numElementsTower_c, n_t_global_c, & +subroutine FAST_ExtInfw_Restart(iTurb_c, CheckpointRootName_c, AbortErrLev_c, dt_c, numblades_c, numElementsPerBlade_c, numElementsTower_c, n_t_global_c, & ExtInfw_Input_from_FAST, ExtInfw_Output_to_FAST, SC_DX_Input_from_FAST, SC_DX_Output_to_FAST, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_ExtInfw_Restart') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Restart !GCC$ ATTRIBUTES DLLEXPORT :: FAST_ExtInfw_Restart #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) CHARACTER(KIND=C_CHAR), INTENT(IN ) :: CheckpointRootName_c(IntfStrLen) INTEGER(C_INT), INTENT( OUT) :: AbortErrLev_c INTEGER(C_INT), INTENT( OUT) :: numblades_c @@ -856,8 +906,12 @@ subroutine FAST_ExtInfw_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, dt_c INTEGER(IntKi) :: Unit REAL(DbKi) :: t_initial_out INTEGER(IntKi) :: NumTurbines_out + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) CHARACTER(*), PARAMETER :: RoutineName = 'FAST_Restart' + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + CALL NWTC_Init() ! transfer the character array from C to a Fortran string: CheckpointRootName = TRANSFER( CheckpointRootName_c, CheckpointRootName ) @@ -904,7 +958,6 @@ end subroutine FAST_ExtInfw_Restart subroutine FAST_ExtLoads_Restart(iTurb, CheckpointRootName_c, AbortErrLev_c, dt_c, numblades_c, & n_t_global_c, ExtLd_Input_from_FAST, ExtLd_Parameter_from_FAST, ExtLd_Output_to_FAST, & SC_DX_Input_from_FAST, SC_DX_Output_to_FAST, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_ExtLoads_Restart') -!DEC$ ATTRIBUTES DLLEXPORT::FAST_ExtLoads_Restart IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_ExtLoads_Restart @@ -1062,22 +1115,25 @@ subroutine SetExternalInflow_pointers(iTurb, ExtInfw_Input_from_FAST, ExtInfw_Ou end subroutine SetExternalInflow_pointers !================================================================================================================================== -subroutine FAST_CFD_Prework(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Prework') -!DEC$ ATTRIBUTES DLLEXPORT::FAST_CFD_Prework +subroutine FAST_CFD_Prework(iTurb_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Prework') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Prework !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Prework #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish ! we can't continue because we might over-step some arrays that are allocated to the size of the simulation - if (iTurb .eq. (NumTurbines-1) ) then + if (iTurb == NumTurbines) then IF (n_t_global == Turbine(iTurb)%p_FAST%n_TMax_m1 + 1) THEN ! we call update an extra time in Simulink, which we can ignore until the time shift with outputs is solved n_t_global = n_t_global + 1 ErrStat_c = ErrID_None @@ -1105,22 +1161,25 @@ subroutine FAST_CFD_Prework(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_ end subroutine FAST_CFD_Prework !================================================================================================================================== -subroutine FAST_CFD_UpdateStates(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_UpdateStates') -!DEC$ ATTRIBUTES DLLEXPORT::FAST_CFD_UpdateStates +subroutine FAST_CFD_UpdateStates(iTurb_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_UpdateStates') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_UpdateStates !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_UpdateStates #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish ! we can't continue because we might over-step some arrays that are allocated to the size of the simulation - if (iTurb .eq. (NumTurbines-1) ) then + if (iTurb == NumTurbines ) then IF (n_t_global == Turbine(iTurb)%p_FAST%n_TMax_m1 + 1) THEN ! we call update an extra time in Simulink, which we can ignore until the time shift with outputs is solved n_t_global = n_t_global + 1 ErrStat_c = ErrID_None @@ -1144,22 +1203,25 @@ subroutine FAST_CFD_UpdateStates(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST end subroutine FAST_CFD_UpdateStates !================================================================================================================================== -subroutine FAST_CFD_AdvanceToNextTimeStep(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_AdvanceToNextTimeStep') -!DEC$ ATTRIBUTES DLLEXPORT::FAST_CFD_AdvanceToNextTimeStep +subroutine FAST_CFD_AdvanceToNextTimeStep(iTurb_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_AdvanceToNextTimeStep') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_AdvanceToNextTimeStep !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_AdvanceToNextTimeStep #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish ! we can't continue because we might over-step some arrays that are allocated to the size of the simulation - if (iTurb .eq. (NumTurbines-1) ) then + if (iTurb == NumTurbines ) then IF (n_t_global == Turbine(iTurb)%p_FAST%n_TMax_m1 + 1) THEN ! we call update an extra time in Simulink, which we can ignore until the time shift with outputs is solved n_t_global = n_t_global + 1 ErrStat_c = ErrID_None @@ -1180,7 +1242,7 @@ subroutine FAST_CFD_AdvanceToNextTimeStep(iTurb, ErrStat_c, ErrMsg_c) BIND (C, N ! CALL SC_SetInputs(Turbine(iTurb)%p_FAST, Turbine(iTurb)%SrvD%y, Turbine(iTurb)%SC, ErrStat, ErrMsg) ! end if - if (iTurb .eq. (NumTurbines-1) ) then + if (iTurb == NumTurbines ) then n_t_global = n_t_global + 1 end if @@ -1192,36 +1254,43 @@ subroutine FAST_CFD_AdvanceToNextTimeStep(iTurb, ErrStat_c, ErrMsg_c) BIND (C, N end subroutine FAST_CFD_AdvanceToNextTimeStep !================================================================================================================================== -subroutine FAST_CFD_WriteOutput(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_WriteOutput') -!DEC$ ATTRIBUTES DLLEXPORT::FAST_CFD_WriteOutput +subroutine FAST_CFD_WriteOutput(iTurb_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_WriteOutput') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_WriteOutput !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_WriteOutput #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 CALL FAST_WriteOutput_T( t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) end subroutine FAST_CFD_WriteOutput !================================================================================================================================== -subroutine FAST_CFD_Step(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Step') +subroutine FAST_CFD_Step(iTurb_c, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Step') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT !DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Step !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Step #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) INTEGER(C_INT), INTENT( OUT) :: ErrStat_c CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 IF ( n_t_global > Turbine(iTurb)%p_FAST%n_TMax_m1 ) THEN !finish ! we can't continue because we might over-step some arrays that are allocated to the size of the simulation - if (iTurb .eq. (NumTurbines-1) ) then + if (iTurb == NumTurbines ) then IF (n_t_global == Turbine(iTurb)%p_FAST%n_TMax_m1 + 1) THEN ! we call update an extra time in Simulink, which we can ignore until the time shift with outputs is solved n_t_global = n_t_global + 1 ErrStat_c = ErrID_None @@ -1238,7 +1307,7 @@ subroutine FAST_CFD_Step(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Ste CALL FAST_Solution_T( t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) - if (iTurb .eq. (NumTurbines-1) ) then + if (iTurb == NumTurbines ) then n_t_global = n_t_global + 1 end if @@ -1250,47 +1319,53 @@ subroutine FAST_CFD_Step(iTurb, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Ste end subroutine FAST_CFD_Step !================================================================================================================================== -subroutine FAST_CFD_Reset_SubStep(iTurb, n_timesteps, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Reset_SubStep') - IMPLICIT NONE +subroutine FAST_CFD_Reset_SubStep(iTurb_c, n_timesteps, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Reset_SubStep') + IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT - !DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Reset_SubStep - !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Reset_SubStep +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Reset_SubStep +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Reset_SubStep #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - INTEGER(C_INT), INTENT(IN ) :: n_timesteps ! Number of time steps to go back - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - - CALL FAST_Reset_SubStep_T(t_initial, n_t_global-n_timesteps, n_timesteps, Turbine(iTurb), ErrStat, ErrMsg ) - - if (iTurb .eq. (NumTurbines-1) ) then - n_t_global = n_t_global - n_timesteps - end if - - ErrStat_c = ErrStat - ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR - ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) + INTEGER(C_INT), INTENT(IN ) :: n_timesteps ! Number of time steps to go back + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + + CALL FAST_Reset_SubStep_T(t_initial, n_t_global-n_timesteps, n_timesteps, Turbine(iTurb), ErrStat, ErrMsg ) + + if (iTurb == NumTurbines ) then + n_t_global = n_t_global - n_timesteps + end if + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) end subroutine FAST_CFD_Reset_SubStep !================================================================================================================================== -subroutine FAST_CFD_Store_SubStep(iTurb, n_t_global, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Store_SubStep') +subroutine FAST_CFD_Store_SubStep(iTurb_c, n_t_global, ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_CFD_Store_SubStep') IMPLICIT NONE #ifndef IMPLICIT_DLLEXPORT - !DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Store_SubStep - !GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Store_SubStep +!DEC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Store_SubStep +!GCC$ ATTRIBUTES DLLEXPORT :: FAST_CFD_Store_SubStep #endif - INTEGER(C_INT), INTENT(IN ) :: iTurb ! Turbine number - INTEGER(C_INT), INTENT(IN ) :: n_t_global !< loop counter - INTEGER(C_INT), INTENT( OUT) :: ErrStat_c - CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) - - CALL FAST_Store_SubStep_T(t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) - - ErrStat_c = ErrStat - ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR - ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) - + INTEGER(C_INT), INTENT(IN ) :: iTurb_c ! Turbine number, c indexing (starts at 0 for first turbine) + INTEGER(C_INT), INTENT(IN ) :: n_t_global !< loop counter + INTEGER(C_INT), INTENT( OUT) :: ErrStat_c + CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_c(IntfStrLen) + integer(IntKi) :: iTurb ! turbine number: Fortran indexing (starts at 1 for first turbine) + + ! transfer turbine index number from C to Fortran indexing (0 to 1 start) + iTurb = int(iTurb_c,IntKi) + 1 + + CALL FAST_Store_SubStep_T(t_initial, n_t_global, Turbine(iTurb), ErrStat, ErrMsg ) + + ErrStat_c = ErrStat + ErrMsg = TRIM(ErrMsg)//C_NULL_CHAR + ErrMsg_c = TRANSFER( ErrMsg//C_NULL_CHAR, ErrMsg_c ) end subroutine FAST_CFD_Store_SubStep !================================================================================================================================== diff --git a/modules/openfast-library/src/FAST_Library.h b/modules/openfast-library/src/FAST_Library.h index 89fbd014d2..f6b9993ba3 100644 --- a/modules/openfast-library/src/FAST_Library.h +++ b/modules/openfast-library/src/FAST_Library.h @@ -20,7 +20,7 @@ EXTERNAL_ROUTINE void FAST_ExtInfw_Restart(int * iTurb, const char *CheckpointRo int * NumBl, int * NumBlElem, int * NumTwrElem, int * n_t_global, ExtInfw_InputType_t* ExtInfw_Input, ExtInfw_OutputType_t* ExtInfw_Output, SC_DX_InputType_t* SC_DX_Input, SC_DX_OutputType_t* SC_DX_Output, int *ErrStat, char *ErrMsg); -EXTERNAL_ROUTINE void FAST_ExtInfw_Init(int * iTurb, double *TMax, const char *InputFileName, int * TurbineID, char *OutFileRoot, +EXTERNAL_ROUTINE void FAST_ExtInfw_Init(int * iTurb, double *TMax, const char *InputFileName, int * TurbIDforName, char *OutFileRoot, int * NumSC2CtrlGlob, int * NumSC2Ctrl, int * NumCtrl2SC, float * initSCInputsGlob, float * initSCInputsTurbine, int * NumActForcePtsBlade, int * NumActForcePtsTower, float * TurbinePosition, int *AbortErrLev, double * dtDriver, double * dt, int * InflowType, int * NumBl, int * NumBlElem, int * NumTwrElem, int * NodeClusterType, diff --git a/modules/openfast-library/src/FAST_Lin.f90 b/modules/openfast-library/src/FAST_Lin.f90 index f9847771ae..a39320be93 100644 --- a/modules/openfast-library/src/FAST_Lin.f90 +++ b/modules/openfast-library/src/FAST_Lin.f90 @@ -3187,8 +3187,8 @@ SUBROUTINE Linear_ED_InputSolve_dy( p_FAST, y_FAST, SrvD, u_ED, y_ED, y_AD, u_AD ! ED translation displacement-to-ED moment transfer (dU^{ED}/dy^{ED}) from BD root-to-ED hub load transfer: ED_Start = Indx_u_ED_Hub_Start(u_ED, y_FAST) + u_ED%HubPtLoad%NNodes*3 ! start of u_ED%HubPtLoad%Moment field (skip forces) + ED_Out_Start = Indx_y_ED_Hub_Start(y_ED, y_FAST) ! start of y_ED%HubMotion%TranslationDisp field DO k=1,p_FAST%nBeams - ED_Out_Start = Indx_y_ED_BladeRoot_Start(y_ED, y_FAST, k) ! start of y_ED%BladeRootMotion(k)%TranslationDisp field call SumBlockMatrix( dUdy, MeshMapData%BD_P_2_ED_P(k)%dM%m_ud, ED_Start, ED_Out_Start) END DO @@ -3591,8 +3591,9 @@ SUBROUTINE Linear_AD_InputSolve_NoIfW_dy( p_FAST, y_FAST, u_AD, y_ED, BD, MeshMa DO k=1,p_FAST%nBeams AD_Start = Indx_u_AD_Blade_Start(u_AD, y_FAST, k) ! start of u_AD%rotors(1)%BladeMotion(k)%TranslationDisp field - BD_Out_Start = y_FAST%Lin%Modules(Module_BD)%Instance(k)%LinStartIndx(LIN_OUTPUT_COL) - + BD_Out_Start = y_FAST%Lin%Modules(MODULE_BD)%Instance(k)%LinStartIndx(LIN_OUTPUT_COL) & ! start of BD%y(k)%BldMotion%TranslationDisp field + + BD%y(k)%ReactionForce%NNodes * 6 ! 2 fields with 3 components + CALL Assemble_dUdy_Motions(BD%y(k)%BldMotion, u_AD%rotors(1)%BladeMotion(k), MeshMapData%BDED_L_2_AD_L_B(k), AD_Start, BD_Out_Start, dUdy, skipRotAcc=.true.) END DO diff --git a/modules/openfast-library/src/FAST_Registry.txt b/modules/openfast-library/src/FAST_Registry.txt index 183353d1ec..014a148710 100644 --- a/modules/openfast-library/src/FAST_Registry.txt +++ b/modules/openfast-library/src/FAST_Registry.txt @@ -831,7 +831,7 @@ typedef ^ FAST_InitData IceD_InitOutputType OutData_IceD - - typedef ^ FAST_ExternInitType DbKi Tmax - -1 - "External code specified Tmax" s typedef ^ FAST_ExternInitType IntKi SensorType - SensorType_None - "lidar sensor type, which should not be pulsed at the moment; this input should be replaced with a section in the InflowWind input file" - typedef ^ FAST_ExternInitType LOGICAL LidRadialVel - - - "TRUE => return radial component, FALSE => return 'x' direction estimate" - -typedef ^ FAST_ExternInitType IntKi TurbineID - 0 - "ID number for turbine (used to create output file naming convention)" - +typedef ^ FAST_ExternInitType IntKi TurbIDforName - -1 - "ID number for turbine (used to create output file naming convention)" - typedef ^ FAST_ExternInitType ReKi TurbinePos {3} - - "Initial position of turbine base (origin used for graphics or in FAST.Farm)" m typedef ^ FAST_ExternInitType IntKi WaveFieldMod - - - "Wave field handling (-) (switch) 0: use individual HydroDyn inputs without adjustment, 1: adjust wave phases based on turbine offsets from farm origin" - typedef ^ FAST_ExternInitType IntKi NumSC2CtrlGlob - - - "number of global controller inputs [from supercontroller]" - diff --git a/modules/openfast-library/src/FAST_Subs.f90 b/modules/openfast-library/src/FAST_Subs.f90 index dc400a1bff..d664cadaac 100644 --- a/modules/openfast-library/src/FAST_Subs.f90 +++ b/modules/openfast-library/src/FAST_Subs.f90 @@ -166,8 +166,8 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, y_FAST%Lin%WindSpeed = 0.0_ReKi if (present(ExternInitData)) then - CallStart = .not. ExternInitData%FarmIntegration ! .and. ExternInitData%TurbineID == 1 - if (ExternInitData%TurbineID > 0) p_FAST%TDesc = 'T'//trim(num2lstr(ExternInitData%TurbineID)) + CallStart = .not. ExternInitData%FarmIntegration + if (ExternInitData%TurbIDforName >= 0) p_FAST%TDesc = 'T'//trim(num2lstr(ExternInitData%TurbIDforName)) else CallStart = .true. end if @@ -210,7 +210,7 @@ SUBROUTINE FAST_InitializeAll( t_initial, p_FAST, y_FAST, m_FAST, ED, BD, SrvD, if (ExternInitData%FarmIntegration) then ! we're integrating with FAST.Farm CALL FAST_Init( p_FAST, m_FAST, y_FAST, t_initial, InputFile, ErrStat2, ErrMsg2, ExternInitData%TMax, OverrideAbortLev=.false., RootName=ExternInitData%RootName ) else - CALL FAST_Init( p_FAST, m_FAST, y_FAST, t_initial, InputFile, ErrStat2, ErrMsg2, ExternInitData%TMax, ExternInitData%TurbineID, DTdriver=ExternInitData%DTdriver ) ! We have the name of the input file and the simulation length from somewhere else (e.g. Simulink) + CALL FAST_Init( p_FAST, m_FAST, y_FAST, t_initial, InputFile, ErrStat2, ErrMsg2, ExternInitData%TMax, ExternInitData%TurbIDforName, DTdriver=ExternInitData%DTdriver ) ! We have the name of the input file and the simulation length from somewhere else (e.g. Simulink) end if else diff --git a/modules/openfast-library/src/FAST_Types.f90 b/modules/openfast-library/src/FAST_Types.f90 index b04269cff9..fa01557597 100644 --- a/modules/openfast-library/src/FAST_Types.f90 +++ b/modules/openfast-library/src/FAST_Types.f90 @@ -846,7 +846,7 @@ MODULE FAST_Types REAL(DbKi) :: Tmax = -1 !< External code specified Tmax [s] INTEGER(IntKi) :: SensorType = SensorType_None !< lidar sensor type, which should not be pulsed at the moment; this input should be replaced with a section in the InflowWind input file [-] LOGICAL :: LidRadialVel = .false. !< TRUE => return radial component, FALSE => return 'x' direction estimate [-] - INTEGER(IntKi) :: TurbineID = 0 !< ID number for turbine (used to create output file naming convention) [-] + INTEGER(IntKi) :: TurbIDforName = -1 !< ID number for turbine (used to create output file naming convention) [-] REAL(ReKi) , DIMENSION(1:3) :: TurbinePos = 0.0_ReKi !< Initial position of turbine base (origin used for graphics or in FAST.Farm) [m] INTEGER(IntKi) :: WaveFieldMod = 0_IntKi !< Wave field handling (-) (switch) 0: use individual HydroDyn inputs without adjustment, 1: adjust wave phases based on turbine offsets from farm origin [-] INTEGER(IntKi) :: NumSC2CtrlGlob = 0_IntKi !< number of global controller inputs [from supercontroller] [-] @@ -14454,7 +14454,7 @@ subroutine FAST_CopyExternInitType(SrcExternInitTypeData, DstExternInitTypeData, DstExternInitTypeData%Tmax = SrcExternInitTypeData%Tmax DstExternInitTypeData%SensorType = SrcExternInitTypeData%SensorType DstExternInitTypeData%LidRadialVel = SrcExternInitTypeData%LidRadialVel - DstExternInitTypeData%TurbineID = SrcExternInitTypeData%TurbineID + DstExternInitTypeData%TurbIDforName = SrcExternInitTypeData%TurbIDforName DstExternInitTypeData%TurbinePos = SrcExternInitTypeData%TurbinePos DstExternInitTypeData%WaveFieldMod = SrcExternInitTypeData%WaveFieldMod DstExternInitTypeData%NumSC2CtrlGlob = SrcExternInitTypeData%NumSC2CtrlGlob @@ -14528,7 +14528,7 @@ subroutine FAST_PackExternInitType(RF, Indata) call RegPack(RF, InData%Tmax) call RegPack(RF, InData%SensorType) call RegPack(RF, InData%LidRadialVel) - call RegPack(RF, InData%TurbineID) + call RegPack(RF, InData%TurbIDforName) call RegPack(RF, InData%TurbinePos) call RegPack(RF, InData%WaveFieldMod) call RegPack(RF, InData%NumSC2CtrlGlob) @@ -14569,7 +14569,7 @@ subroutine FAST_UnPackExternInitType(RF, OutData) call RegUnpack(RF, OutData%Tmax); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%SensorType); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%LidRadialVel); if (RegCheckErr(RF, RoutineName)) return - call RegUnpack(RF, OutData%TurbineID); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%TurbIDforName); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%TurbinePos); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%WaveFieldMod); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NumSC2CtrlGlob); if (RegCheckErr(RF, RoutineName)) return diff --git a/modules/servodyn/src/ServoDyn.f90 b/modules/servodyn/src/ServoDyn.f90 index a5e683526f..7fa4b05678 100644 --- a/modules/servodyn/src/ServoDyn.f90 +++ b/modules/servodyn/src/ServoDyn.f90 @@ -158,6 +158,8 @@ SUBROUTINE SrvD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitO CALL DispNVD( SrvD_Ver ) CALL GetPath( InitInp%InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + p%PriPath = PriPath + !............................................................................................ ! Read the input file and validate the data ! (note p%NumBl and p%RootName must be set first!) @@ -1484,7 +1486,7 @@ subroutine StC_Blade_Setup(SrvD_InitInp,SrvD_p,InputFileData,SrvD_u,SrvD_y,SrvD_ ! A little bit of information about the StC location if (unsum >0) then write(UnSum, '(A24,i2)') ' Blade StC instance: ',j - write(UnSum, '(10x,A)') 'Input file: '//trim(InputFileData%NStCfiles(j)) + write(UnSum, '(10x,A)') 'Input file: '//trim(InputFileData%BStCfiles(j)) do k=1,StC_InitInp%NumMeshPts write(UnSum, '(10x,A6,I1,A29)') 'Blade ',k,' location (global/inertial): ' write(UnSum, '(20x,3(2x,ES10.3e2))') u(1,j)%Mesh(k)%Position(1:3,1) @@ -5241,7 +5243,7 @@ SUBROUTINE CalculateStandardYaw(t, u, p, m, YawPosCom, YawRateCom, YawPosComInt, CASE ( ControlMode_USER ) ! User-defined from routine UserYawCont(). - CALL UserYawCont ( u%Yaw, u%YawRate, u%WindDir, u%YawErr, p%NumBl, t, p%DT, p%RootName, YawPosCom, YawRateCom ) + CALL UserYawCont ( u%Yaw, u%YawRate, u%WindDir, u%YawErr, p%NumBl, t, p%DT, p%PriPath, YawPosCom, YawRateCom ) CASE ( ControlMode_EXTERN ) ! User-defined from Simulink or LabVIEW @@ -5380,7 +5382,7 @@ SUBROUTINE Pitch_CalcOutput( t, u, p, x, xd, z, OtherState, BlPitchCom, ElecPwr, CASE ( ControlMode_USER ) ! User-defined from routine PitchCntrl(). - CALL PitchCntrl ( u%BlPitch, ElecPwr, u%LSS_Spd, u%TwrAccel, p%NumBl, t, p%DT, p%RootName, BlPitchCom ) + CALL PitchCntrl ( u%BlPitch, ElecPwr, u%LSS_Spd, u%TwrAccel, p%NumBl, t, p%DT, p%PriPath, BlPitchCom ) CASE ( ControlMode_EXTERN ) ! User-defined from Simulink or LabVIEW. @@ -5733,7 +5735,7 @@ SUBROUTINE Torque_CalcOutput( t, u, p, x, xd, z, OtherState, y, m, ErrStat, ErrM CASE ( ControlMode_USER ) ! User-defined HSS brake model. - CALL UserHSSBr ( y%GenTrq, y%ElecPwr, u%HSS_Spd, p%NumBl, t, p%DT, p%RootName, HSSBrFrac ) + CALL UserHSSBr ( y%GenTrq, y%ElecPwr, u%HSS_Spd, p%NumBl, t, p%DT, p%PriPath, HSSBrFrac ) IF ( ( HSSBrFrac < 0.0_ReKi ) .OR. ( HSSBrFrac > 1.0_ReKi ) ) THEN ! 0 (off) <= HSSBrFrac <= 1 (full); else Abort. ErrStat = ErrID_Fatal @@ -5938,8 +5940,8 @@ SUBROUTINE CalculateTorque( t, u, p, m, GenTrq, ElecPwr, ErrStat, ErrMsg ) CASE ( ControlMode_USER ) ! User-defined generator model. - ! CALL UserGen ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, DT, p%GenEff, DelGenTrq, DirRoot, GenTrq, ElecPwr ) - CALL UserGen ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, p%DT, p%GenEff, 0.0_ReKi, p%RootName, GenTrq, ElecPwr ) + CALL UserGen ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, p%DT, p%GenEff, 0.0_ReKi, p%PriPath, GenTrq, ElecPwr ) + END SELECT @@ -5974,7 +5976,7 @@ SUBROUTINE CalculateTorque( t, u, p, m, GenTrq, ElecPwr, ErrStat, ErrMsg ) CASE ( ControlMode_USER ) ! User-defined variable-speed control for routine UserVSCont(). - CALL UserVSCont ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, p%DT, p%GenEff, 0.0_ReKi, p%RootName, GenTrq, ElecPwr ) + CALL UserVSCont ( u%HSS_Spd, u%LSS_Spd, p%NumBl, t, p%DT, p%GenEff, 0.0_ReKi, p%PriPath, GenTrq, ElecPwr ) CASE ( ControlMode_DLL ) ! User-defined variable-speed control from Bladed-style DLL diff --git a/modules/servodyn/src/ServoDyn_Registry.txt b/modules/servodyn/src/ServoDyn_Registry.txt index 4f3ab877c7..30013c593f 100644 --- a/modules/servodyn/src/ServoDyn_Registry.txt +++ b/modules/servodyn/src/ServoDyn_Registry.txt @@ -439,6 +439,7 @@ typedef ^ ParameterType IntKi StCCmode - - - "Structural control control mode {0 typedef ^ ParameterType IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - typedef ^ ParameterType IntKi NumOuts_DLL - - - "Number of logging channels output from the DLL (set at initialization)" - typedef ^ ParameterType CHARACTER(1024) RootName - - - "RootName for writing output files" - +typedef ^ ParameterType CHARACTER(1024) PriPath - - - "Path of the primary SrvD input file " - typedef ^ ParameterType OutParmType OutParam {:} - - "Names and units (and other characteristics) of all requested output parameters" - typedef ^ ParameterType CHARACTER(1) Delim - - - "Column delimiter for output text files" - # parameters for Bladed Interface (dynamic-link library) diff --git a/modules/servodyn/src/ServoDyn_Types.f90 b/modules/servodyn/src/ServoDyn_Types.f90 index 9d2f6de448..806629157d 100644 --- a/modules/servodyn/src/ServoDyn_Types.f90 +++ b/modules/servodyn/src/ServoDyn_Types.f90 @@ -450,6 +450,7 @@ MODULE ServoDyn_Types INTEGER(IntKi) :: NumOuts = 0_IntKi !< Number of parameters in the output list (number of outputs requested) [-] INTEGER(IntKi) :: NumOuts_DLL = 0_IntKi !< Number of logging channels output from the DLL (set at initialization) [-] CHARACTER(1024) :: RootName !< RootName for writing output files [-] + CHARACTER(1024) :: PriPath !< Path of the primary SrvD input file [-] TYPE(OutParmType) , DIMENSION(:), ALLOCATABLE :: OutParam !< Names and units (and other characteristics) of all requested output parameters [-] CHARACTER(1) :: Delim !< Column delimiter for output text files [-] LOGICAL :: UseBladedInterface = .false. !< Flag that determines if BladedInterface was used [-] @@ -4621,6 +4622,7 @@ subroutine SrvD_CopyParam(SrcParamData, DstParamData, CtrlCode, ErrStat, ErrMsg) DstParamData%NumOuts = SrcParamData%NumOuts DstParamData%NumOuts_DLL = SrcParamData%NumOuts_DLL DstParamData%RootName = SrcParamData%RootName + DstParamData%PriPath = SrcParamData%PriPath if (allocated(SrcParamData%OutParam)) then LB(1:1) = lbound(SrcParamData%OutParam, kind=B8Ki) UB(1:1) = ubound(SrcParamData%OutParam, kind=B8Ki) @@ -5141,6 +5143,7 @@ subroutine SrvD_PackParam(RF, Indata) call RegPack(RF, InData%NumOuts) call RegPack(RF, InData%NumOuts_DLL) call RegPack(RF, InData%RootName) + call RegPack(RF, InData%PriPath) call RegPack(RF, allocated(InData%OutParam)) if (allocated(InData%OutParam)) then call RegPackBounds(RF, 1, lbound(InData%OutParam, kind=B8Ki), ubound(InData%OutParam, kind=B8Ki)) @@ -5316,6 +5319,7 @@ subroutine SrvD_UnPackParam(RF, OutData) call RegUnpack(RF, OutData%NumOuts); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%NumOuts_DLL); if (RegCheckErr(RF, RoutineName)) return call RegUnpack(RF, OutData%RootName); if (RegCheckErr(RF, RoutineName)) return + call RegUnpack(RF, OutData%PriPath); if (RegCheckErr(RF, RoutineName)) return if (allocated(OutData%OutParam)) deallocate(OutData%OutParam) call RegUnpack(RF, IsAllocAssoc); if (RegCheckErr(RF, RoutineName)) return if (IsAllocAssoc) then diff --git a/modules/subdyn/src/SubDyn_Driver.f90 b/modules/subdyn/src/SubDyn_Driver.f90 index de2bb6e880..0d0f1ba4f5 100644 --- a/modules/subdyn/src/SubDyn_Driver.f90 +++ b/modules/subdyn/src/SubDyn_Driver.f90 @@ -517,111 +517,5 @@ function is_int(string, x) read(string,fmt,iostat=e) x is_int = e == 0 end function is_int - - !> Read a delimited file with one line of header - subroutine ReadDelimFile(Filename, nCol, Array, errStat, errMsg, nHeaderLines, priPath) - character(len=*), intent(in) :: Filename - integer, intent(in) :: nCol - real(ReKi), dimension(:,:), allocatable, intent(out) :: Array - integer(IntKi) , intent(out) :: errStat ! Status of error message - character(*) , intent(out) :: errMsg ! Error message if ErrStat /= ErrID_None - integer(IntKi), optional, intent(in ) :: nHeaderLines - character(*) , optional, intent(in ) :: priPath ! Primary path, to use if filename is not absolute - integer :: UnIn, i, j, nLine, nHead - character(len= 2048) :: line - integer(IntKi) :: errStat2 ! local status of error message - character(ErrMsgLen) :: errMsg2 ! temporary Error message - character(len=2048) :: Filename_Loc ! filename local to this function - ErrStat = ErrID_None - ErrMsg = "" - - Filename_Loc = Filename - if (present(priPath)) then - if (PathIsRelative(Filename_Loc)) Filename_Loc = trim(PriPath)//trim(Filename) - endif - - - ! Open file - call GetNewUnit(UnIn) - call OpenFInpFile(UnIn, Filename_Loc, errStat2, errMsg2); call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'ReadDelimFile') - if (errStat >= AbortErrLev) return - ! Count number of lines - nLine = line_count(UnIn) - allocate(Array(nLine-1, nCol), stat=errStat2); errMsg2='allocation failed'; call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'ReadDelimFile') - if (errStat >= AbortErrLev) return - ! Read header - nHead=1 - if (present(nHeaderLines)) nHead = nHeaderLines - do i=1,nHead - read(UnIn, *, IOSTAT=errStat2) line - errMsg2 = ' Error reading line '//trim(Num2LStr(1))//' of file: '//trim(Filename_Loc) - call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'ReadDelimFile') - if (errStat >= AbortErrLev) return - enddo - ! Read data - do I = 1,nLine-1 - read (UnIn,*,IOSTAT=errStat2) (Array(I,J), J=1,nCol) - errMsg2 = ' Error reading line '//trim(Num2LStr(I+1))//' of file: '//trim(Filename_Loc) - call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'ReadDelimFile') - if (errStat >= AbortErrLev) return - end do - close(UnIn) - end subroutine ReadDelimFile - - !> Counts number of lines in a file - integer function line_count(iunit) - integer, intent(in) :: iunit - character(len=2048) :: line - ! safety for infinite loop.. - integer :: i - integer, parameter :: nline_max=100000000 ! 100 M - line_count=0 - do i=1,nline_max - line='' - read(iunit,'(A)',END=100)line - line_count=line_count+1 - enddo - if (line_count==nline_max) then - print*,'Error: maximum number of line exceeded for line_count' - STOP - endif - 100 if(len(trim(line))>0) then - line_count=line_count+1 - endif - rewind(iunit) - return - end function - !> Perform linear interpolation of an array, where first column is assumed to be ascending time values - !! First value is used for times before, and last value is used for time beyond - subroutine interpTimeValue(array, time, iLast, values) - real(ReKi), dimension(:,:), intent(in) :: array !< vector of time steps - real(DbKi), intent(in) :: time !< time - integer, intent(inout) :: iLast - real(ReKi), dimension(:), intent(out) :: values !< vector of values at given time - integer :: i - real(ReKi) :: alpha - if (array(iLast,1)> time) then - values = array(iLast,2:) - elseif (iLast == size(array,1)) then - values = array(iLast,2:) - else - ! Look for index - do i=iLast,size(array,1) - if (array(i,1)<=time) then - iLast=i - else - exit - endif - enddo - if (iLast==size(array,1)) then - values = array(iLast,2:) - else - ! Linear interpolation - alpha = (array(iLast+1,1)-time)/(array(iLast+1,1)-array(iLast,1)) - values = array(iLast,2:)*alpha + array(iLast+1,2:)*(1-alpha) - !print*,'time', array(iLast,1), '<=', time,'<', array(iLast+1,1), 'fact', alpha - endif - endif - end subroutine interpTimeValue !---------------------------------------------------------------------------------------------------------------------------------- END PROGRAM diff --git a/modules/turbsim/src/CohStructures.f90 b/modules/turbsim/src/CohStructures.f90 index 9c1ad52141..a20ad42f18 100644 --- a/modules/turbsim/src/CohStructures.f90 +++ b/modules/turbsim/src/CohStructures.f90 @@ -766,7 +766,7 @@ SUBROUTINE CohStr_WriteEvents( RootName, p_CohStr, e_CohStr, y_CohStr, TScale, U CHARACTER(MaxMsgLen) :: ErrMsg2 ! Message describing error (local) - CHARACTER(200) :: InpFile ! Name of the input file + CHARACTER(1024) :: InpFile ! Name of the input file TYPE (Event), POINTER :: PtrCurr => NULL() ! Pointer to the current event TYPE (Event), POINTER :: PtrPrev => NULL() ! Pointer to the previous event (for deallocation purposes) diff --git a/modules/turbsim/src/Profiles.f90 b/modules/turbsim/src/Profiles.f90 index 7135b92856..36ca07fde0 100644 --- a/modules/turbsim/src/Profiles.f90 +++ b/modules/turbsim/src/Profiles.f90 @@ -122,7 +122,7 @@ SUBROUTINE GetChebCoefs(p, UJetMax_IsKnown, ErrStat, ErrMsg) ! valid only for jet WindProfileType -IMPLICIT NONE + IMPLICIT NONE TYPE(TurbSim_ParameterType),INTENT(INOUT) :: p ! TurbSim parameters LOGICAL, INTENT(IN) :: UJetMax_IsKnown diff --git a/modules/turbsim/src/TS_FileIO.f90 b/modules/turbsim/src/TS_FileIO.f90 index 70b5f91a76..d4a5814137 100644 --- a/modules/turbsim/src/TS_FileIO.f90 +++ b/modules/turbsim/src/TS_FileIO.f90 @@ -72,7 +72,7 @@ SUBROUTINE ReadInputFile(InFile, p, OtherSt_RandNum, ErrStat, ErrMsg) LOGICAL :: UseDefault ! Whether or not to use a default value LOGICAL :: IsUnusedParameter ! Whether or not this variable will be ignored - CHARACTER(200) :: Line ! An input line + CHARACTER(1024) :: Line ! An input line CHARACTER(1) :: Line1 ! The first character of an input line INTEGER(IntKi) :: ErrStat2 ! Temporary Error status diff --git a/modules/turbsim/src/TurbSim.f90 b/modules/turbsim/src/TurbSim.f90 index 5aa65491aa..768a43b859 100644 --- a/modules/turbsim/src/TurbSim.f90 +++ b/modules/turbsim/src/TurbSim.f90 @@ -82,7 +82,7 @@ PROGRAM TurbSim INTEGER(IntKi) :: ErrStat ! allocation status CHARACTER(MaxMsgLen) :: ErrMsg ! error message -CHARACTER(200) :: InFile ! Name of the TurbSim input file. +CHARACTER(1024) :: InFile ! Name of the TurbSim input file. CHARACTER(20) :: FlagArg ! flag argument from command line diff --git a/modules/turbsim/src/TurbSim_Types.f90 b/modules/turbsim/src/TurbSim_Types.f90 index c4a6071032..07a7773018 100644 --- a/modules/turbsim/src/TurbSim_Types.f90 +++ b/modules/turbsim/src/TurbSim_Types.f90 @@ -90,8 +90,8 @@ MODULE TurbSim_Types REAL(ReKi) :: DistScl ! Disturbance scale for AeroDyn coherent turbulence events - CHARACTER(200) :: CTEventPath ! String used to store the name of the coherent event definition file - CHARACTER(200) :: CTEventFile ! String used to store the name of the coherent event definition file + CHARACTER(1024) :: CTEventPath ! String used to store the name of the coherent event definition file + CHARACTER(1024) :: CTEventFile ! String used to store the name of the coherent event definition file CHARACTER( 3) :: CTExt ! String used to determine the type of coherent structures ("dns" or "les") END TYPE CohStr_ParameterType @@ -276,8 +276,8 @@ MODULE TurbSim_Types INTEGER :: US = -1 ! I/O unit for summary file. - CHARACTER(200) :: DescStr ! String used to describe the run (and the first line of the summary file) - CHARACTER(197) :: RootName ! Root name of the I/O files. + CHARACTER(1024) :: DescStr ! String used to describe the run (and the first line of the summary file) + CHARACTER(1024) :: RootName ! Root name of the I/O files. TYPE(RandNum_ParameterType) :: RNG ! parameters for random numbers p_RandNum TYPE(Grid_ParameterType) :: grid ! parameters for TurbSim (specify grid/frequency size) TYPE(Meteorology_ParameterType) :: met ! parameters for TurbSim diff --git a/reg_tests/CMakeLists.txt b/reg_tests/CMakeLists.txt index 156d28e541..9d51bb2620 100644 --- a/reg_tests/CMakeLists.txt +++ b/reg_tests/CMakeLists.txt @@ -42,7 +42,7 @@ option(CTEST_NO_RUN_FLAG "Complete the regression test comparison but do not ex # Set the OpenFAST executable configuration option and default set(CTEST_OPENFAST_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast/openfast${CMAKE_EXECUTABLE_SUFFIX}" CACHE FILEPATH "Specify the OpenFAST executable to use in testing.") -if(BUILD_OPENFAST_CPP_DRIVER) +if(BUILD_OPENFAST_CPP_API) # Set the OpenFAST executable configuration option and default set(CTEST_OPENFASTCPP_EXECUTABLE "${CMAKE_BINARY_DIR}/glue-codes/openfast-cpp/openfastcpp${CMAKE_EXECUTABLE_SUFFIX}" CACHE FILEPATH "Specify the OpenFAST C++ executable to use in testing.") endif() diff --git a/reg_tests/CTestList.cmake b/reg_tests/CTestList.cmake index dec7c8ae21..cd87b2ba50 100644 --- a/reg_tests/CTestList.cmake +++ b/reg_tests/CTestList.cmake @@ -314,11 +314,12 @@ of_regression("StC_test_OC4Semi" "openfast;servodyn;hydrod 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") +of_regression("Tailfin_FreeYaw1DOF_Unsteady" "openfast;elastodyn;aerodyn15") of_aeromap_regression("5MW_Land_AeroMap" "aeromap;elastodyn;aerodyn15") # OpenFAST C++ API test -if(BUILD_OPENFAST_CPP_DRIVER) +if(BUILD_OPENFAST_CPP_API) of_cpp_interface_regression("5MW_Land_DLL_WTurb_cpp" "openfast;fastlib;cpp") endif() @@ -342,8 +343,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" "-highpass=0.05" "openfast;linear;elastodyn;aerodyn") -#of_regression_linear("Fake5MW_AeroLin_B3_UA6" "-highpass=0.05" "openfast;linear;elastodyn;aerodyn") +of_regression_linear("Fake5MW_AeroLin_B1_UA4_DBEMT3" "-highpass=0.05" "openfast;linear;elastodyn;aerodyn") +of_regression_linear("Fake5MW_AeroLin_B3_UA6" "-highpass=0.05" "openfast;linear;elastodyn;aerodyn") of_regression_linear("WP_Stationary_Linear" "" "openfast;linear;elastodyn") of_regression_linear("Ideal_Beam_Fixed_Free_Linear" "-highpass=0.10" "openfast;linear;beamdyn") of_regression_linear("Ideal_Beam_Free_Free_Linear" "-highpass=0.10" "openfast;linear;beamdyn") @@ -356,6 +357,7 @@ of_regression_linear("StC_test_OC4Semi_Linear_Nac" "" "openfas of_regression_linear("StC_test_OC4Semi_Linear_Tow" "" "openfast;linear;servodyn;stc") of_regression_linear("WP_Stationary_Linear" "" "openfast;linear;elastodyn") of_regression_linear("5MW_OC3Spar_Linear" "" "openfast;linear;map;hydrodyn") +of_regression_linear("5MW_OC3Mnpl_Linear" "" "openfast;linear;hydrodyn;servodyn;moordyn") # FAST Farm regression tests if(BUILD_FASTFARM) diff --git a/reg_tests/executeUnsteadyAeroRegressionCase.py b/reg_tests/executeUnsteadyAeroRegressionCase.py index b8ca227924..ab9e5255a2 100644 --- a/reg_tests/executeUnsteadyAeroRegressionCase.py +++ b/reg_tests/executeUnsteadyAeroRegressionCase.py @@ -90,7 +90,7 @@ # create the local output directory and initialize it with input files -renameDict={'UA'+str(i)+'.UA.out':'UA'+str(i)+'.UA_ref.out' for i in [2,3,4,5,6,7]} +renameDict={'UA'+str(i)+'.outb':'UA'+str(i)+'_ref.outb' for i in [2,3,4,5,6,7]} rtl.copyTree(inputsDirectory, testBuildDirectory, renameDict=renameDict , excludeExt=['.sum']) @@ -116,8 +116,8 @@ def Error(msg): ### Compare output with for dvrf in dvrFiles: simName = os.path.splitext(os.path.basename(dvrf))[0] - localOutFile = os.path.join(testBuildDirectory, simName + '.UA.out') - baselineOutFile = os.path.join(inputsDirectory, simName + '.UA.out') + localOutFile = os.path.join(testBuildDirectory, simName + '.outb') + baselineOutFile = os.path.join(inputsDirectory, simName + '.out') # TODO TODO if not os.path.exists(localOutFile): Error('File does not exist: {}'.format(localOutFile)) diff --git a/reg_tests/r-test b/reg_tests/r-test index bf69eed152..5a064f10ac 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit bf69eed1525f3263ca8858dfb931a8284d72fe3d +Subproject commit 5a064f10ac66f0808f4d0ffb0973c1c15b44c6c3 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..21752feaf4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +# Python dependencies used for testing +numpy +vtk +Bokeh>=2.4,!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3 \ No newline at end of file diff --git a/share/docker/Dockerfile b/share/docker/Dockerfile new file mode 100644 index 0000000000..742d6b0a59 --- /dev/null +++ b/share/docker/Dockerfile @@ -0,0 +1,73 @@ +# Copyright 2016-2024 National Renewable Energy Laboratory +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +ARG BASE=ubuntu:jammy + +# Build stage 1: builds openfast. +FROM ${BASE} AS build + +# Install dependencies +# For gfortran-8 +# RUN add-apt-repository ppa:ubuntu-toolchain-r/test -y +# apt-get install gfortran-8 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y \ + software-properties-common \ + build-essential \ + cmake \ + cmake-curses-gui \ + gcc \ + gfortran \ + git \ + libopenblas-dev \ + make \ + && rm -rf /var/lib/apt/lists/* + +# Copy in the checked-out code version. +WORKDIR /openfast +COPY . . + +# Build the project. +RUN mkdir build +WORKDIR /openfast/build + +# NOTE: building with optimizations on (RELEASE or RELWITHDEBINFO), the virtual machine +# will require about 6GB of memory. Otherwise, the gfortran compiler will exit with an +# "internal error" +ENV FC=/usr/bin/gfortran +ARG CMAKE_OPTIONS="-DBUILD_TESTING=OFF -DBUILD_FASTFARM=ON -DDOUBLE_PRECISION=OFF -DCMAKE_BUILD_TYPE=RELEASE" +RUN cmake .. ${CMAKE_OPTIONS} + +ARG BUILD_CORES=4 +RUN make -j${BUILD_CORES} install + +# Build stage 2: provides built openfast in a small image. +FROM ${BASE} as production +COPY --from=build /openfast/install /openfast/install + +ARG TIMEZONE=UTC +ENV DEBIAN_FRONTEND=noninteractive TZ=${TIMEZONE} + +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y \ + libopenblas-dev \ + libgomp1 \ + nano \ + && rm -rf /var/lib/apt/lists/* + +# Make `openfast` command work. +ENV PATH=/openfast/install/bin:$PATH diff --git a/share/docker/README.md b/share/docker/README.md new file mode 100644 index 0000000000..82517f7b1f --- /dev/null +++ b/share/docker/README.md @@ -0,0 +1,42 @@ +# OpenFAST docker images + +## Summary +The `Dockerfile` in this directory can be used to reliably build OpenFAST as a docker image that can be run locally and +in the cloud without much setup. By default, it's based on Ubuntu Jammy and is optimised in size and performance for +production use. A multi-stage build is used, producing an Ubuntu image with just `libblas-dev`, `liblapack-dev`, `nano` +and `openfast` added. The image built by this `Dockerfile` can be customised at build time using build arguments. + +## Image registry +Production images of OpenFAST for the `linux/amd64` platform are available on the +[NREL docker hub](https://hub.docker.com/r/nrel/openfast). + +## Build arguments +Provide any of the following build arguments to customise the image at build time. + +| Name | Type | Allowed values | Default | Description | +| --------------- | ------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `BASE` | String | Any valid docker image URI that has the `apt` package manager installed. | `ubuntu:jammy` | The docker image to base the OpenFAST image on. | +| `CMAKE_OPTIONS` | String | Any number of valid space-separated `cmake` options in the same format they're normally passed to `cmake` directly. See the options relevant to OpenFAST [here.](https://openfast.readthedocs.io/en/main/source/install/index.html#openfast-cmake-options) | `-DBUILD_TESTING=OFF -DBUILD_FASTFARM=ON -DDOUBLE_PRECISION=OFF -DCMAKE_BUILD_TYPE=RELEASE` | Options to control how CMake is used to build OpenFAST. | +| `BUILD_CORES` | Integer | Any integer greater than 0. | `4` | The number of cores to use to build OpenFAST with `make`. | +| `TIMEZONE` | String | Any [valid timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). | `UTC` | The timezone to use when running OpenFAST. | + +For example, to build OpenFAST v3.5.3 for the `linux/amd64` platform and set `CMAKE_OPTIONS` so the testing tree is built: + +```shell +# Run from the root of this repository. +git checkout v3.5.3 +docker build -f share/docker/Dockerfile -t openfast:3.5.3 --platform=linux/amd64 --build-arg=CMAKE_OPTIONS='-DBUILD_TESTING=ON' . +``` + +**NOTE:** This version of the `Dockerfile` is only available in v3.5.3 and up of this repository. To build earlier +versions of OpenFAST, check out the code at that version and recreate the `Dockerfile` from v3.5.3 (or above) in the +checked-out repository first. + +## Building development images +Development images can be built from the production image as a base. Simply start a new `Dockerfile` with: + +```dockerfile +FROM nrel/openfast:3.5.3 +``` + +Images can be built for different platforms using the `--platform` option when building the image. diff --git a/share/docker/openfast_ubuntu/Dockerfile b/share/docker/openfast_ubuntu/Dockerfile deleted file mode 100644 index 8470e56230..0000000000 --- a/share/docker/openfast_ubuntu/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -# -# Copyright 2016 National Renewable Energy Laboratory -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -FROM ubuntu:bionic - -# Install dependencies - -# For gfortran-8 -# RUN add-apt-repository ppa:ubuntu-toolchain-r/test -y -# apt-get install gfortran-8 - -ENV DEBIAN_FRONTEND=noninteractive TZ=America/Denver - -RUN apt update -qq && \ - apt install -y software-properties-common build-essential && \ - add-apt-repository ppa:git-core/ppa -y && \ - apt install -y python3-pip && \ - apt install -y cmake cmake-curses-gui && \ - apt install -y gcc gfortran make && \ - apt install -y libblas-dev liblapack-dev && \ - apt install -y git && \ - apt install -y nano - -RUN pip3 install numpy - -# Configure the environment -ENV FC=/usr/bin/gfortran - -# Clone the project -RUN git clone --recursive https://github.com/openfast/openfast.git openfast -WORKDIR /openfast - -# Build the project -RUN mkdir build -WORKDIR /openfast/build - -# NOTE: building with optimizations on (RELEASE or RELWITHDEBINFO), the virtual machine -# will require about 6GB of memoery. Otherwise, the gfortran compiler will exit with an -# "internal error" -RUN cmake .. -DBUILD_TESTING=ON -DDOUBLE_PRECISION=ON -DCMAKE_BUILD_TYPE=RELWITHDEBINFO -RUN make -j4 install diff --git a/vs-build/AeroDyn/AeroDyn_Driver.sln b/vs-build/AeroDyn/AeroDyn_Driver.sln index 2941d4240d..f9a1f191eb 100644 --- a/vs-build/AeroDyn/AeroDyn_Driver.sln +++ b/vs-build/AeroDyn/AeroDyn_Driver.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.33529.622 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "AeroDyn_Driver", "AeroDyn_Driver.vfproj", "{97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}" ProjectSection(ProjectDependencies) = postProject @@ -44,26 +44,26 @@ Global {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release|Win32.Build.0 = Release|Win32 {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release|x64.ActiveCfg = Release|x64 {97CEFEB9-1DCB-470E-A231-E1DA2F21A9CE}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.sln b/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.sln index e9a3790633..295a6d1e8d 100644 --- a/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.sln +++ b/vs-build/AeroDyn_Inflow_c_binding/AeroDyn_Inflow_c_binding.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.33529.622 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "AeroDyn_Inflow_c_binding", "AeroDyn_Inflow_c_binding.vfproj", "{5D991B19-D4F1-4F29-8A9D-FC36DFF07290}" ProjectSection(ProjectDependencies) = postProject @@ -44,26 +44,26 @@ Global {5D991B19-D4F1-4F29-8A9D-FC36DFF07290}.Release|Win32.Build.0 = Release|Win32 {5D991B19-D4F1-4F29-8A9D-FC36DFF07290}.Release|x64.ActiveCfg = Release|x64 {5D991B19-D4F1-4F29-8A9D-FC36DFF07290}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/BeamDyn/BeamDyn-w-registry.sln b/vs-build/BeamDyn/BeamDyn-w-registry.sln index 0261cbdc7e..573fd9f26f 100644 --- a/vs-build/BeamDyn/BeamDyn-w-registry.sln +++ b/vs-build/BeamDyn/BeamDyn-w-registry.sln @@ -38,22 +38,22 @@ Global {815C302F-A93D-4C22-9329-7112345113C0}.Release|Win32.Build.0 = Release|Win32 {815C302F-A93D-4C22-9329-7112345113C0}.Release|x64.ActiveCfg = Release|x64 {815C302F-A93D-4C22-9329-7112345113C0}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/FAST-farm/FAST-Farm.sln b/vs-build/FAST-farm/FAST-Farm.sln index b7159f95f0..bab76b0d32 100644 --- a/vs-build/FAST-farm/FAST-Farm.sln +++ b/vs-build/FAST-farm/FAST-Farm.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "FASTlib", "..\FASTlib\FASTlib.vfproj", "{1A440C5B-CBA6-47D9-9CC2-C1CBA8C00BF9}" ProjectSection(ProjectDependencies) = postProject @@ -55,18 +55,18 @@ Global {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|Win32.Build.0 = Release|Win32 {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|x64.ActiveCfg = Release|x64 {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 {F47C7C94-2A7F-4CBE-B834-1BC7DD3FE692}.Debug|Win32.ActiveCfg = Debug|Win32 {F47C7C94-2A7F-4CBE-B834-1BC7DD3FE692}.Debug|Win32.Build.0 = Debug|Win32 {F47C7C94-2A7F-4CBE-B834-1BC7DD3FE692}.Debug|x64.ActiveCfg = Debug|x64 @@ -83,4 +83,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {13BD9A6C-E2B3-4423-AA37-D06CB518B5B2} + EndGlobalSection EndGlobal diff --git a/vs-build/FAST-farm/FAST-Farm.vfproj b/vs-build/FAST-farm/FAST-Farm.vfproj index e88a7fab0d..e7c3152f30 100644 --- a/vs-build/FAST-farm/FAST-Farm.vfproj +++ b/vs-build/FAST-farm/FAST-Farm.vfproj @@ -6,7 +6,7 @@ - + diff --git a/vs-build/FAST/FAST.sln b/vs-build/FAST/FAST.sln index ec3d691059..f1f08b2b9d 100644 --- a/vs-build/FAST/FAST.sln +++ b/vs-build/FAST/FAST.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27428.2043 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "FAST", "FAST.vfproj", "{18AE8067-CCC6-4479-A0DB-C4089EF9FE71}" ProjectSection(ProjectDependencies) = postProject @@ -110,30 +110,30 @@ Global {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|Win32.Build.0 = Release|Win32 {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|x64.ActiveCfg = Release|x64 {BF86702A-CB17-4050-8AE9-078CDC5910D3}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Matlab|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Matlab|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Double|Win32.ActiveCfg = Debug_Matlab|Win32 {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Double|x64.ActiveCfg = Debug_Matlab|x64 {C3C93CC0-EDD7-438F-988C-1F917FAEFA67}.Debug_Matlab|Win32.ActiveCfg = Debug_Matlab|Win32 diff --git a/vs-build/HydroDyn/HydroDynDriver.sln b/vs-build/HydroDyn/HydroDynDriver.sln index 10a8c91d84..17c738b756 100644 --- a/vs-build/HydroDyn/HydroDynDriver.sln +++ b/vs-build/HydroDyn/HydroDynDriver.sln @@ -1,7 +1,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30503.244 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "HydroDynDriver", "HydroDynDriver.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" EndProject diff --git a/vs-build/HydroDyn_c_binding/HydroDyn_c_binding.sln b/vs-build/HydroDyn_c_binding/HydroDyn_c_binding.sln index 7d4579ad4f..753bece4fc 100644 --- a/vs-build/HydroDyn_c_binding/HydroDyn_c_binding.sln +++ b/vs-build/HydroDyn_c_binding/HydroDyn_c_binding.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30503.244 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{A2215CCC-531E-454C-A1F0-E502FB697697}") = "HydroDyn_c_binding.dll", "HydroDyn_c_binding.vfproj", "{FDA4A02B-B3A7-4D06-847C-941BE44E76FB}" +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "HydroDyn_c_binding", "HydroDyn_c_binding.vfproj", "{FDA4A02B-B3A7-4D06-847C-941BE44E76FB}" ProjectSection(ProjectDependencies) = postProject {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} EndProjectSection @@ -38,24 +38,27 @@ Global {FDA4A02B-B3A7-4D06-847C-941BE44E76FB}.Release|Win32.Build.0 = Release|Win32 {FDA4A02B-B3A7-4D06-847C-941BE44E76FB}.Release|x64.ActiveCfg = Release|x64 {FDA4A02B-B3A7-4D06-847C-941BE44E76FB}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {49DA4583-1BAB-4459-8F53-EB898075680D} + EndGlobalSection EndGlobal diff --git a/vs-build/InflowWind/InflowWind_driver.sln b/vs-build/InflowWind/InflowWind_driver.sln index c1f9d4753e..6bc82e29a1 100644 --- a/vs-build/InflowWind/InflowWind_driver.sln +++ b/vs-build/InflowWind/InflowWind_driver.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.33529.622 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "InflowWind_driver", "InflowWind_driver.vfproj", "{3BBE2741-5B28-47BC-9E7F-3E1D172838FB}" ProjectSection(ProjectDependencies) = postProject @@ -44,26 +44,26 @@ Global {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release|Win32.Build.0 = Release|Win32 {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release|x64.ActiveCfg = Release|x64 {3BBE2741-5B28-47BC-9E7F-3E1D172838FB}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_OpenMP|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/InflowWind_c_binding/InflowWind_c_binding.sln b/vs-build/InflowWind_c_binding/InflowWind_c_binding.sln index 03d412a05f..24fde71ef9 100644 --- a/vs-build/InflowWind_c_binding/InflowWind_c_binding.sln +++ b/vs-build/InflowWind_c_binding/InflowWind_c_binding.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "InflowWind_c_binding", "InflowWind_c_binding.vfproj", "{5D991B19-D4F1-4F29-8A9D-FC36DFF07290}" ProjectSection(ProjectDependencies) = postProject @@ -38,24 +38,27 @@ Global {5D991B19-D4F1-4F29-8A9D-FC36DFF07290}.Release|Win32.Build.0 = Release|Win32 {5D991B19-D4F1-4F29-8A9D-FC36DFF07290}.Release|x64.ActiveCfg = Release|x64 {5D991B19-D4F1-4F29-8A9D-FC36DFF07290}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7DBCF286-C404-4F79-A1F2-3A04C4859A09} + EndGlobalSection EndGlobal diff --git a/vs-build/MoorDyn/MoorDynDriver.sln b/vs-build/MoorDyn/MoorDynDriver.sln index 26252cc2de..29001b4108 100644 --- a/vs-build/MoorDyn/MoorDynDriver.sln +++ b/vs-build/MoorDyn/MoorDynDriver.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31613.86 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{A1373E92-2C9A-4B4D-BE47-0B46E317E1A8}") = "MoorDynDriver", "MoorDynDriver.vfproj", "{E91DED35-18F8-415F-9719-59DFBA79CB2C}" EndProject diff --git a/vs-build/MoorDyn_c_binding/MoorDyn_c_binding.sln b/vs-build/MoorDyn_c_binding/MoorDyn_c_binding.sln index fa41e081d7..d9d928b345 100644 --- a/vs-build/MoorDyn_c_binding/MoorDyn_c_binding.sln +++ b/vs-build/MoorDyn_c_binding/MoorDyn_c_binding.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31613.86 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{EBD10482-CD70-4409-938D-86A4D2DED606}") = "MoorDyn_c_binding.dll", "MoorDyn_c_binding.vfproj", "{25689C95-9A3C-41A1-B0E6-5B292B6EFBE9}" +Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "MoorDyn_c_binding", "MoorDyn_c_binding.vfproj", "{25689C95-9A3C-41A1-B0E6-5B292B6EFBE9}" ProjectSection(ProjectDependencies) = postProject {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} = {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16} EndProjectSection @@ -38,22 +38,22 @@ Global {25689C95-9A3C-41A1-B0E6-5B292B6EFBE9}.Release|Win32.Build.0 = Release|Win32 {25689C95-9A3C-41A1-B0E6-5B292B6EFBE9}.Release|x64.ActiveCfg = Release|x64 {25689C95-9A3C-41A1-B0E6-5B292B6EFBE9}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/Registry/FAST_Registry.sln b/vs-build/Registry/FAST_Registry.sln index 689421c6c9..c79ad0bab2 100644 --- a/vs-build/Registry/FAST_Registry.sln +++ b/vs-build/Registry/FAST_Registry.sln @@ -1,20 +1,20 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27428.2043 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FAST_Registry", "FAST_Registry.vcxproj", "{DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Debug|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Debug|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Debug|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Debug|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/RunRegistry.bat b/vs-build/RunRegistry.bat index 28964ae6dc..f56a56f29d 100644 --- a/vs-build/RunRegistry.bat +++ b/vs-build/RunRegistry.bat @@ -45,6 +45,8 @@ SET SrvD_Loc=%Modules_Loc%\servodyn\src SET BD_Loc=%Modules_Loc%\beamdyn\src SET SC_Loc=%Modules_Loc%\supercontroller\src +SET LD_Loc=%Modules_Loc%\lindyn\src + SET AWAE_Loc=%Modules_Loc%\awae\src SET WD_Loc=%Modules_Loc%\wakedynamics\src SET Farm_Loc=%Root_Loc%\glue-codes\fast-farm\src @@ -184,6 +186,12 @@ SET Output_Loc=%CURR_LOC% %REGISTRY% "%CURR_LOC%\UnsteadyAero_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" GOTO checkError +:LD +SET CURR_LOC=%LD_Loc% +SET Output_Loc=%CURR_LOC% +%REGISTRY% "%CURR_LOC%\LinDyn_Registry.txt" -I "%NWTC_Lib_Loc%" -I "%CURR_LOC%" -O "%Output_Loc%" +GOTO checkError + :FVW SET CURR_LOC=%AD_Loc% SET Output_Loc=%CURR_LOC% diff --git a/vs-build/SC_DLL/SC_DLL.sln b/vs-build/SC_DLL/SC_DLL.sln index 54daab58ef..ce221a58ed 100644 --- a/vs-build/SC_DLL/SC_DLL.sln +++ b/vs-build/SC_DLL/SC_DLL.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.40629.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "SC_DLL", "SC_DLL.vfproj", "{183CC593-AD4C-9643-81C1-7D6085A9A5ED}" EndProject diff --git a/vs-build/SubDyn/SubDyn.sln b/vs-build/SubDyn/SubDyn.sln index 817a37d8cd..fc06af462c 100644 --- a/vs-build/SubDyn/SubDyn.sln +++ b/vs-build/SubDyn/SubDyn.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.4.33205.214 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.902 MinimumVisualStudioVersion = 10.0.40219.1 Project("{6989167D-11E4-40FE-8C1A-2192A86A7E90}") = "SubDyn", "SubDyn.vfproj", "{815C302F-A93D-4C22-9329-717B085113C0}" ProjectSection(ProjectDependencies) = postProject @@ -38,22 +38,22 @@ Global {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.Build.0 = Release|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Release|x64.ActiveCfg = Release|x64 {815C302F-A93D-4C22-9329-717B085113C0}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Debug|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Debug|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Debug|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Debug|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/UnsteadyAero/UnsteadyAero.sln b/vs-build/UnsteadyAero/UnsteadyAero.sln index 4daa940c63..9fbf677f9f 100644 --- a/vs-build/UnsteadyAero/UnsteadyAero.sln +++ b/vs-build/UnsteadyAero/UnsteadyAero.sln @@ -38,22 +38,22 @@ Global {815C302F-A93D-4C22-9329-717B085113C0}.Release|Win32.Build.0 = Release|Win32 {815C302F-A93D-4C22-9329-717B085113C0}.Release|x64.ActiveCfg = Release|x64 {815C302F-A93D-4C22-9329-717B085113C0}.Release|x64.Build.0 = Release|x64 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|Win32 - {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|Win32 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Debug|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release_Double|x64.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|Win32.Build.0 = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.ActiveCfg = Release|x64 + {DA16A3A6-3297-4628-9E46-C6FA0E3C4D16}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/vs-build/UnsteadyAero/UnsteadyAero.vfproj b/vs-build/UnsteadyAero/UnsteadyAero.vfproj index 4cb89b2f83..0903d0848b 100644 --- a/vs-build/UnsteadyAero/UnsteadyAero.vfproj +++ b/vs-build/UnsteadyAero/UnsteadyAero.vfproj @@ -5,7 +5,7 @@ - + @@ -15,7 +15,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -35,7 +35,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -55,7 +55,7 @@ - + @@ -65,7 +65,7 @@ - + @@ -75,7 +75,7 @@ - + @@ -120,6 +120,27 @@ + + + + + + + + + + + + + + + + + + + + +